As mentioned earlier, the weather data is obtained by the Raspberry Pi and communicates the data with control characters via the serial port. We will discuss the control signals used in this project.
Let's get started by reviewing the Python script used to operate the weather display.
subversion
is not installed on the Raspberry Pi, it can be installed using the following command:sudo apt-get install subversion
svn checkout http://python-weather-api.googlecode.com/svn/trunk/ python-weather-api-read-only
cd python-weather-api-read-only python3 setup.py build python3 setup.py install
pywapi
, and time (for delay) modules for the project:#!/usr/bin/env python import serial import glob import pprint import pywapi from time import sleep
scan()
function identifies all the serial ports available on the Raspberry Pi:# Establish serial port communication def scan(): return glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*')+ glob.glob('/dev/ttyACM*') sport_data = scan() for name in scan(): serialport = serial.Serial(name,9600) sleep(5) serialport.write(bytes("A",'ascii')) sleep(1) response = serialport.read() if(response==b'A'): sport = name serialport.close() break seport = serial.Serial(sport,9600,timeout=45)
A
and await a response. When a response with the byte A
is received, we identify and save the serial port. After identification, we will establish a connection with the Arduino.result = pywapi.get_weather_from_noaa('KORD')
temperature = int(float(result['temp_f']))
temperature_string= "S"+str(temperature) #print(temperature_string) seport.write(bytes(temperature_string,'ascii'))
if(temperature>40): seport.write(bytes("G",'ascii')) sleep(5) seport.write(bytes("P4",'ascii')) sleep(5) seport.write(bytes("M1",'ascii')) sleep(5)
if(result['weather']=='Light Snow') or (result['weather']=='Snow') or (result['weather']=='Flurries'): seport.write(bytes("H",'ascii')) sleep(5) seport.write(bytes("T-2",'ascii')) sleep(5)
Let us review on the control signal and control flow of the weather clock.
The following flowchart shows what happens in the Arduino when a control character is received from the Raspberry Pi.
A
. The Arduino responds with an acknowledgement character A
:if(serial_read=='A'){ Serial.print("A"); }
S
. The received data is converted to a signed integer and passed as an argument to the 7-Segment display libraries:if(serial_read=='S') { while(Serial.available()){ sb = Serial.read(); sevenseg_string[serInIndx] = sb; serInIndx++; temp=0; } temp=atoi(sevenseg_string); memset(sevenseg_string,0,9); }
S
is received, we read all the characters into the buffer sevenseg_string
. The string is converted to an integer using the atoi
function and stored in the temp
variable. The buffer is cleared at the end of the cycle. This method takes sub-zero temperatures into consideration.R
, G
, and, B
respectively. Each color indicates a unique weather condition, namely, blue indicates cold weather, green indicates fair weather conditions, and red color indicates impeding danger in weather conditions:if(serial_read=='R' || serial_read=='G' || serial_read=='B') { color_bit=serial_read; } if(color_bit=='R'){ lightsequence_red(); } else if(color_bit=='G'){ lightsequence_green(); } else if(color_bit=='B'){ lightsequence_blue(); }
+
, and counterclockwise direction is indicated by -
.if( serial_read == 'P' ) { while(Serial.available()) { sb = Serial.read(); serInString[serInIndx] = sb; serInIndx++; } }
P
and store the rest of the string in a buffer. Once the data is stored in the buffer, we will determine whether the first character is + or -.if(serInString[0]==43){ int var_serial=0; for(serOutIndx=1;serOutIndx<serInIndx;serOutIndx++) { var_serial = var_serial*10+(serInString[serOutIndx]-48); } motorSpeed=20; for(int i=0;i<var_serial;i++){ clockwise(); }
var_serial = var_serial*10+(serInString[serOutIndx]-48);
clockwise()
and counterclockwise()
functions.H
is transmitted via the serial port, the arrow is moved towards the home position:if(serial_read=='H'){ reset_stepper(); lightsequence(); }
reset_stepper()
function takes care of setting the arrow to the home position:void reset_stepper(void){ uint8_t val; // Get the value from the sensor if (ReadByte(sensorAddr, 0x0, &val) == 0) { // The second LSB indicates if something was not detected, i.e., // LO = object detected, HI = nothing detected while(val & 0x2) { motorSpeed=20; Serial.println("Nothing detected"); if(ReadByte(sensorAddr, 0x0, &val) == 0){ clockwise();//We keep going clockwise until the arrow is detected } } } else { Serial.println("Failed to read from sensor"); } }
reset_stepper()
function, we will execute the stepper motor's clockwise routine until the object is detected. The sensor reference manual mentions that an object is detected if the second LSB is set to low. Hence, the stepper rotates in the clockwise direction until a low signal is detected.const int mydata[6][2] PROGMEM = {
1, 10,
2, 18,
3, 28,
4, 43,
5, 54,
6, 66};
1
through 6
in the array correspond to the weather forecast indicators starting in the counterclockwise direction. The second position indicates the number of positions from the home position to point to that particular weather condition.T
. In order to point to the weather forecast, Rain
, the command would be T-6
. When a character T
is received, we store the data received in a buffer. It is confirmed that the second character received after the letter T
is a number between 1
and 6
. We will retrieve the corresponding position data from the flash memory using the pgm_read_word_near()
function. Once the data is retrieved, the stepper motor control routine is executed for the desired number of steps.if( serial_read == 'T' ) { while(Serial.available()) { sb = Serial.read(); serInString[serInIndx] = sb; serInIndx++; } } int var_serial=serInString[1]-48; serInIndx=0; if(var_serial>0 && var_serial <=6) { steps=pgm_read_word_near(&mydata[(var_serial-1)][1]); Serial.println(steps); } if(serInString[0]==45){ motorSpeed=20; for(int i=0;i<steps;i++){ counterclockwise(); }
3.138.170.174