Using python on v2 to monitor arduino and control things

We had fun with this display during mayor libby’s made in oakland  inauguration at the american steel studios … it shows how easy it is to use arduino from linux. In this case visualizing how fast one is riding a bike using a v2 controller, a magnet on the wheel of a bicycle, a hall effect sensor, relays and traffic light leds – and some code.

IMG_20150111_175846i think the bike should be facing the other side, hah  – but the sensor cable was short. kids have fun either way

IMG_20150111_190349-nopm- (1)i must remember to make it harder and more rewarding for the stronger ones.

the main parts are shown below

halleffectLedseach rotation of the wheel causes an electric pulse to flow in the hall effect sensor as the permanent magnet spins by. the hall effect sensor is connect to the atmega chip on interrupt 2 (pin 21). we detect how fast the wheel is spinning by shutting down all processes on the atmega 2560 chip for 1 second and counting the interrupts on pin 21. the count gives us the speed in revolutions per second. given the wheel diameter we can determine say distance travelled etc.

the 2560 code used is shown below. this is from the hall effect sensor example programs.

// read RPM

int half_revolutions = 0;

int rpm = 0;

unsigned long lastmillis = 0;

// this code will be executed every time the interrupt 0 (pin2) gets low.

void rpm_fan(){

half_revolutions++;

}

void setup(){

Serial.begin(38400);

attachInterrupt(2, rpm_fan, FALLING);

}

void loop(){

if (millis() - lastmillis == 1000){ //Uptade every one second, this will be equal to reading frecuency (Hz).

detachInterrupt(0);//Disable interrupt when calculating

rpm = half_revolutions * 60; // Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use half_revolutions * 30.

Serial.print("RPM =t"); //print the word "RPM" and tab.

Serial.print(rpm); // print the rpm value.

Serial.print("t Hz=t"); //print the word "Hz".

Serial.println(half_revolutions); //print revolutions per second or Hz. And print new line or enter.

half_revolutions = 0; // Restart the RPM counter

lastmillis = millis(); // Uptade lasmillis

attachInterrupt(2, rpm_fan, FALLING); //enable interrupt

}

}

this produces lines on the arduino ide serial console, that look as follows:

RPM = 0 Hz=0

RPM = 1 Hz=60

RPM = 2 Hz=120

etc.

we read these streams using python on the ar9331 side and process them to decide which led light to turn on based on bike speed. the leds are connected to the ar9331 8 gpios with open collector transistors (ie. relays connect directly to the linux microcomputer)

the python script is shown below:

#!/usr/bin/python

import re

import serial

from time import sleep

from subprocess import call

#arduinp screams on serial port

port = '/dev/ttyATH0'

ser = serial.Serial(port, 38400)

def processLine(line):

#process speed data for each lne by turning on the appropriate led in sequence

line = line.rstrip() #remove end of line control characters

print line;

rpmLine = line.split('t')

rpm = int(rpmLine[1])

print rpm

if rpm >= 480:

call(["relay1on"])

call(["relay2on"])

call(["relay3on"])

call(["relay4on"])

call(["relay5on"])

call(["relay6on"])

call(["relay7on"])

call(["relay8on"])

elif rpm >=420:

call(["relay1on"])

call(["relay2on"])

call(["relay3on"])

call(["relay4on"])

call(["relay5on"])

call(["relay6on"])

call(["relay7off"])

call(["relay8off"])

elif rpm >=360:

call(["relay1on"])

call(["relay2on"])

call(["relay3on"])

call(["relay4on"])

call(["relay5on"])

call(["relay6on"])

call(["relay7off"])

call(["relay8off"])

elif rpm >= 300:

call(["relay1on"])

call(["relay2on"])

call(["relay3on"])

call(["relay4on"])

call(["relay5on"])

call(["relay6off"])

call(["relay7off"])

call(["relay8off"])

elif rpm >= 240:

call(["relay1on"])

call(["relay2on"])

call(["relay3on"])

call(["relay4on"])

call(["relay5off"])

call(["relay6off"])

call(["relay7off"])

call(["relay8off"])

elif rpm >= 180:

call(["relay1on"])

call(["relay2on"])

call(["relay3on"])

call(["relay4off"])

call(["relay5off"])

call(["relay6off"])

call(["relay7off"])

call(["relay8off"])

elif rpm >= 120:

call(["relay1on"])

call(["relay2on"])

call(["relay3off"])

call(["relay4off"])

call(["relay5off"])

call(["relay6off"])

call(["relay7off"])

call(["relay8off"])

elif rpm >= 60:

call(["relay1on"])

call(["relay2off"])

call(["relay3off"])

call(["relay4off"])

call(["relay5off"])

call(["relay6off"])

call(["relay7off"])

call(["relay8off"])

else rpm < 60: call(["relay1off"]) call(["relay2off"]) call(["relay3off"]) call(["relay4off"]) call(["relay5off"]) call(["relay6off"]) call(["relay7off"]) call(["relay8off"]) rpm = 0 #----------------main proram------------------------ # read controller serial streams and process them to determine led light sequence. print 'Starting Controller Monitor' line ='' while True: data = ser.read() #read arduino data(serial strems) validChars = re.compile('[^Wd_{}:]*') #remove unwanted characters validLine = validChars.match(line) if (validLine): if(data == "n"): #do we have a complete line to process line=line.rstrip() try: processLine(line) #build json object and send to mongo db except ValueError: raise InputError('bad serial data {}'. format(input)) line = "" else: line = line + data #build line using characters

To run this program copy it to the v2 controller using scp and use python to execute it.