231a-aaArduinoProject

From CSclasswiki
Jump to: navigation, search

Groduino

Introduction

The ideal incarnation of this project would be a sealed-off environment that could be completely regulated by a computer. Completely enclosed terrariums, for example, are not completely inexhaustible; they can eventually run out of water, go through a long period of time with inadequate light, etc. It was my hope that, with a computer's help, supplementing water supplies and light, the lifespan and style of the terrarium could be significantly improved.

The second motivation for the project was the simple fact that I am very bad at keeping plants. I often forget to water them, and my own room receives very little to no sunlight -- a very sad place to be a plant! Since programming a sealed-off terrarium would prove impossible with the time and resources currently available to me, the project was accordingly adjusted to cater itself towards a human user, who would adjust levels as necessary him/herself.

The prototype created for this class uses sensors to measure and regulate light, water, and temperature levels; it will automatically adjust the first as needed, according to both weather and light input, keep the user aware of the current temperature, and and alert the user when the plant needs to be watered.


Program input/output

Input

  • Arduino:
    • A light sensor to monitor weather it is light (ie: currently sunny) or dark (ie: currently cloudy) outside.
    • The temperature sensor monitors the current temperature of the plant's environment.
    • The moisture sensor circuit determines whether or not the plant currently has water.
  • Assembly:
    • Assembly executes through c a wget command to retrieve a weather report from a webpage. Parsing it, it determines whether today's weather is sunny or cloudy, and outputs light accordingly.


Output

  • Arduino:
    • A lamp connected by relay to the Arduino, which is triggered either on or off according to commands sent by assembly.
  • Assembly:
    • A constant status report of the template: DATE
    • A sound file plays when the plant needs to be watered.

Design Notes

The program is designed, for the purposes of a demo, to run for 10 minutes, updating its status every minute. It was initially meant to run for 11+ hours, updating itself every half-hour; it is fairly easy to change this in the program. Simply change the following lines:

cmp	eax, 	39600
...
add	eax, 1800

When first run, the program retrieves a webpage with the current weather. It parses it and locates the weather for the area. It then checks the system time.

If it is before 7 am or after 6:30 pm:
The system is turned off and it does not retrieve input or send output.
If it is after...
The system is turned on. Weather is parsed.

If weather is cloudy
Relay/lamp is initially set to "on", to give the plant light.
If weather is sunny
Relay/lamp is initially set to off, as it is assumed the plant will not need light.

Because it only checks the weather once at the beginning of the program (it might be possible to check weather updates with every status update -- if system("rm weather.txt") is added to the c program, so that when getWeather() is called, it doesn't make a duplicate that doesn't get checked -- and if the txt file being downloaded updates itself regularly to begin with...), the system will not know when cloudy weather clears up or if a previously sunny day turns into a downpour. Thus, LDR input is checked.

If LDR detects light
Relay/lamp is switched to off, or kept off.
If LDR does not detect light
Relay/lamp is switched on, or kept on.

If moisture sensor detects moisture
Status is changed to reflect as such; no further actions taken.
If moisture sensor does not detect moisture
Status is changed to reflect as such; warning sound is played.

The temperature was meant to be displayed in Fahrenheit, and a conversion function can be seen in the driver.c program; I was unable to figure out and/or decide how to pass appropriate variables between the three programs, however. I had originally thought to use assembly to write the analog output to the c buffer, which would convert it and pass it back, however this resulted in segfaults. I decided, in the end, to merely display the raw Arduino input -- as it rises when it gets hot and falls when it gets cold, hopefully the user can make some determination as to whether any strange or extreme temperatures were detected.

Issues/Future features

  • As noted in the previous section, I was unable to figure out how to display temperature in Fahrenheit.

  • I didn't come across very many bugs, but unfortunately the program is rather simple (and clunkily programmed in Assembly) -- had I more time, I would have liked to include more features. The conversion of the date to text (that is, from 12/18 to December 18th) was meant to be done through a binary search, but due to struggles with short jump errors I ended up only programming a conversion for the sole month of December (at any other time, it will not display the month at all.)

  • Furthermore, I had originally planned to include a closing statement of some sort -- to take the average of the temperature for that day, for example, and display how much sunlight the plant had received. The first and second would merely have involved writing functions that stored variables in the loop and then calculated an average or added everything up.

  • I also had lofty plans of being able to tell you just how dehydrated the plant was, but this would have involved switching the moisture circuit over to an analog pin instead of a digital one. This sounds simple, but the calibration involved would have taken time I didn't have -- to figure out which level of dehydration corresponded to which seemingly-randomly-output number. I also meant to have it so the plant would thank you after you watered it (that is, if the status abruptly jumped from dehydrated to hydrated.)

  • Finally, I wish I'd figured out a better way of getting the weather. In all honesty, it's not accurate at all -- percentage of precipitation has very little to do with whether the day will be cloudy or sunny! Furthermore, the textfile doesn't update itself, and isn't even for the local area. I had originally planned to grab the weather off of this page -- it has a static url, updates itself every day, and very plainly says "CLOUDY" or "SUNNY" -- but at the time I could not figure out how to isolate that text from the surrounding html tags, which were the same as any of the text displayed on the page... Not even searching for the particular image next to the cloudy/sunny text would have helped, as obviously that would change depending on the actual weather, and the extended attributes in that particular image tag are present in other image tags on the page. There were other options -- writing a php page, or scripting something in perl that could possibly write the weather to a text file -- but I wanted to focus more on the actual assembly than external issues.

To run

To run:

nasm -f elf Project.asm
gcc -o Project driver.c asm_io.o Project.o -lm
./Project -b 9600 -p /dev/ttyUSB0

Schematics

231a-aaSchematicsUpdated.jpg

Hardware circuits

Relay

  • Battery-powered lamp
  • 5V Relay
  • IN4004 Diode
  • 2N22222 Transistor
  • 1K Resistor

I am using a battery-powered lamp that, when given output by the Arduino, is made considerably brighter. By providing this relay with a small amount of voltage (using the transistor as a switch and powering it with Arduino's 5V output, protecting it against back EMF current with the diode), the relay is switched on and the lamp is allowed to be powered.


Test

When the LDR does not detect light (it is covered/dark in the room), the relay switches on the lamp.

int ledPin = 10;
int ldrPin = 5;
int ldrVal = 0;

void setup()
{
 pinMode(ledPin, OUTPUT);
}

void loop()
{
   ldrVal = digitalRead(ldrPin);
   if (ldrVal == 0){
     digitalWrite(ledPin, HIGH);
     delay(1000);
   }
   digitalWrite(ledPin, LOW);
}

LDR

Moisture Sensor

  • Two galvanized nails
  • 2N3904 transistor
  • 100 Ohm resistor
  • 10K Ohm resistor

Using the nails as probes (soldering them to wires beforehand), it is possible to measure the amount of water in the soil of a plant. Wire them to the transistor through the resistors, and connect them to the Arduino pin 0 and through the power bus... When the soil is wet the water is connecting the two probes closing the circuit and electricity is going through creating the signal for the controller.


Test

When moisture is present, allowing current to pass, the LED at pin 13 turns on.

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  VARIABLES

int pin = 2;   // analog pin 2
int light = 13;

int pinVal = 0;  // variable use to read input data

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  SETUP

void setup() {

// call the Serial function, this will output values into the console - click the SERIAL MONITOR button
pinMode(light, OUTPUT);

// there is no need to declare INPUT PIN for the analogs
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  LOOP


void loop(){

pinVal = digitalRead(pin);   // read input LDR value

// output 'LDR_val' value into the console
if (pinVal == 1){
 digitalWrite(light, HIGH);
 delay(1000);
}else{
 digitalWrite(light, LOW);
 delay(1000);
 
}
} 

Thermistor

Test

#include <math.h>

double Thermister(int RawADC) {
 double Temp;
 Temp = log(((10240000/RawADC) - 10000));
 Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
 Temp = Temp - 273.15;            // Convert Kelvin to Celcius
 Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
 return Temp;
}

void setup() {
 Serial.begin(115200);
}

void loop() {
 Serial.println(int(Thermister(analogRead(5))));  // display Fahrenheit
 delay(100);
}

Software

C programs

This program is used to communicate with the arduino, retrieve a webpage, retrieve the system time, play a sound, and transform an analog reading into a Fahrenheit temperature. It has been cobbled together from the [c program used in the arduino lab], the [tutorial in playing a file in c], and the c program included in the comments of [this] assembly program to retrieve local time.

Assembly program

The assembly program used in this project handles the majority of the logic flow and coordinates commands between the shell subcommands, the system, the c program, and the arduino.

Arduino program

The arduino program used in the project does very little, beyond setting Digital Pin 10 as the relay output, and waiting to receive commands from the Arduino to turn certain circuits on and off, and to provide readings.