Components and supplies
IR Break Beam Sensor
Arduino UNO
Raspberry Pi 3 Model B
Inky pHAT
Tools and machines
Hot glue gun (generic)
Project description
Code
Gerbil Exercise Wheel Monitor
arduino
Measuring the distance and speed of a Gerbil in an exercise wheel.
1// Gerbil exercise wheel monitor 2// by Stuart Bryant - 25-Feb-19 3 4// Include the library code: 5#include "Wire.h" 6#include "Adafruit_LiquidCrystal.h" 7 8// Connect via i2c, default address #0 (A0-A2 not jumpered): 9Adafruit_LiquidCrystal lcd(0); 10 11// Define LED pin: 12#define LED_PIN 13 13 14// Define IR sensor pin: 15#define IR_SENSOR 3 16 17// Define wheel diameter constant [mm]: 18#define Diameter 130 19 20// Variable for recording distance: 21float Distance = 0; 22 23// Define integer variables: 24int Counts = 0; // counts the number of times that the IR beam has been broken 25int n = 0; // counter for Header function 26int DistInt = 0; // rounded distance 27 28// Define timing variables: 29float LastTrigger = 0.0; 30float Period = 0.0; 31float Speed = 0.0; 32float MaxSpeed = 0.0; 33float LastSpeed = 0.0; 34 35 36void setup() { 37 38 // Open serial monitor: 39 Serial.begin(9600); 40 Serial.println("Gerbil monitor!"); 41 Serial.println("Distance [m] | Speed [mph] | Max Speed [mph]"); 42 43 // set up the LCD's number of rows and columns: 44 lcd.begin(16, 2); 45 // Print a text to LCD: 46 lcd.clear(); 47 lcd.print("Meters"); 48 lcd.setCursor(0, 1); 49 lcd.print("Max mph"); 50 51 // Setup the LED: 52 pinMode(LED_PIN,OUTPUT); 53 54 // Setup the IR sensor input with a pull-up resistor: 55 pinMode(IR_SENSOR,INPUT_PULLUP); 56 57 // Attach interrupt tp IR sensor pin: 58 attachInterrupt(digitalPinToInterrupt(IR_SENSOR),BeamBreak, FALLING); 59} 60 61 62void BeamBreak() { 63 64 Counts++; 65 66 // Calculated distance in meters: 67 Distance = Diameter * 3.14 * Counts / 1000; 68 DistInt = Distance; 69 Period = millis() - LastTrigger; 70 Speed = Diameter / Period * 7.028; // pi x 1000ms x 2.23694 mph/ m/s 71 72 if (Speed - LastSpeed < 3) { // filters out false readings 73 74 LastSpeed = Speed; // updates max speed 75 if (Speed > MaxSpeed) { 76 MaxSpeed = Speed; 77 } 78 79 // Print data to serial monitor: 80 Serial.print(Distance); 81 Serial.print(" "); 82 Serial.print(Speed); 83 Serial.print(" "); 84 Serial.println(MaxSpeed); 85 86 Header(); 87 LastTrigger = millis(); 88 } 89} 90 91// Function for formatting the serial monitor output with headers: 92void Header() { 93 if (n > 4) { 94 Serial.println("Distance [m] | Speed [mph] | Max Speed [mph]"); 95 n = 0; 96 } 97 n++; 98} 99 100void loop() { 101 102 // Illuminate board LED each time IR beam is broken: 103 if (digitalRead(IR_SENSOR) == LOW) { 104 digitalWrite(LED_PIN, HIGH); 105 } 106 else 107 { 108 digitalWrite(LED_PIN, LOW); 109 } 110 111 // Print data to LCD: 112 lcd.setCursor(9, 0); 113 lcd.print(DistInt); 114 lcd.setCursor(9, 1); 115 lcd.print(MaxSpeed); 116} 117
Inky pHAT Display of Gerbil Data
python
Code for Raspberry Pi
1# Inky pHAT display of gerbil data 2# by Stuart Bryant 15-Apr-19 3 4# Inky pHAT set-up: 5 6from inky import InkyPHAT 7import numpy as np 8import math 9import csv 10 11 12inky_display = InkyPHAT("yellow") 13inky_display.set_border(inky_display.YELLOW) 14 15# Time imports and set-up: 16import calendar as c 17import time as t 18import datetime as dt 19 20weekdays = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'] 21 22#Set-up serial connection to Arduino: 23import serial 24ser = serial.Serial('/dev/ttyACM0', 9600) # open serial port to Arduino 25ser.flushInput() # remove any data from the serial buffer 26 27# Import Python Image Library: 28from PIL import Image, ImageFont, ImageDraw 29 30# Create a new canvas to draw on: 31img = Image.open("/home/pi/GerbilProject/G6.png") 32draw = ImageDraw.Draw(img) 33 34# Font definitions: 35from font_fredoka_one import FredokaOne 36font = ImageFont.truetype(FredokaOne, 22) 37font2 = ImageFont.truetype("Piboto-Bold.ttf", 14) 38font3 = ImageFont.truetype("Piboto-Bold.ttf", 7) 39 40# Create array for storing hourly distance: 41dist_array = np.full(24,1) 42 43# Create array for storing daily distance: 44week_array = np.full(7,0) 45 46# Import previous 24 hours of data: 47with open('24hrData.csv', 'rt') as f: 48 csv_reader = csv.reader(f, quoting=csv.QUOTE_NONNUMERIC) 49 for line in csv_reader: 50 for n in range (0, 24): 51 dist_array[n] = line[n] 52f.close() 53 54# Import previous daily distances: 55with open('WeekData.csv', 'rt') as f: 56 csv_reader = csv.reader(f, quoting=csv.QUOTE_NONNUMERIC) 57 for line in csv_reader: 58 for n in range (0, 7): 59 week_array[n] = line[n] 60f.close() 61 62m = np.amax(dist_array) # maxiumum hourly distance 63maxSpeed = 0 # maximum speed variable 64 65 66def screenUpdate(): 67 # Create a new canvas to draw on 68 img = Image.open("/home/pi/GerbilProject/G6.png") 69 draw = ImageDraw.Draw(img) 70 71 # Title text: 72 title = "Snuggles & Gingy" 73 w, h = font.getsize(title) 74 x = (inky_display.WIDTH / 2) - (w / 2) 75 y = 7 76 draw.text((x,y), title, inky_display.YELLOW, font) 77 78 # Data lines: 79 textDay = yesterday() + "'s data:" 80 draw.text((8,40), textDay, inky_display.BLACK, font2) 81 82 textDistance ="Distance: " + str(np.sum(dist_array)) + "m" 83 draw.text((8,60), textDistance, inky_display.BLACK, font2) 84 85 textSpeed ="Max Speed: " + str(maxSpeed) + "mph" 86 draw.text((8,80), textSpeed, inky_display.BLACK, font2) 87 88 m = np.amax(dist_array) 89 # Draw histogram data: 90 for n in range (0, 24): 91 draw.line((129+n*2,60, 129+n*2,60-dist_array[n]/m*20), fill=1) 92 93 # Histogram axes: 94 draw.line((127,40, 127,62), fill=2) 95 draw.line((125,60, 175,60), fill=2) 96 97 # x-axis labels: 98 draw.text((121,62), "0", inky_display.BLACK, font3) 99 draw.text((146,62), "12", inky_display.BLACK, font3) 100 draw.text((170,62), "24", inky_display.BLACK, font3) 101 102 # Set image and display: 103 inky_display.set_image(img) 104 inky_display.show() 105 106def yesterday(): 107 yesterday = weekdays[c.weekday(t.gmtime().tm_year,t.gmtime().tm_mon,t.gmtime().tm_mday)-1] 108 return yesterday 109 110def ArduinoSerial(input): 111 ser.write(bytes(input.encode('ascii'))) 112 t.sleep(0.1) # wait for Arduino to respond 113 if(ser.inWaiting() >0): 114 output = "" 115 line = ser.readline() 116 l = len(line) 117 l = l - 2 118 for char in line: 119 output = output + chr(char) 120 outputFloat = float(output[:l]) 121 return outputFloat 122 123 124screenUpdate() 125 126 127step = 3600 128 129s = t.time() 130s = math.ceil(s/step)*step 131interval = step # one hour interval 132lastDistance = 0 133 134while 1: 135 if (t.time() > s): 136 distance = ArduinoSerial('d') 137 maxSpeed = ArduinoSerial('s') 138 139 deltaDistance = distance - lastDistance 140 lastDistance = distance 141 dist_array[t.gmtime().tm_hour-1] = deltaDistance 142 143 s = s + interval 144 145 print("###################################") 146 print("Time: "+str(t.gmtime().tm_hour)+":"+str(t.gmtime().tm_min)+":"+str(t.gmtime().tm_sec)) 147 print("Interval distance =",deltaDistance, "Total distance:", distance) 148 print("Max speed today: "+str(maxSpeed)) 149 print("Distance array (last 24 hours):") 150 print(dist_array) 151 152 # Save last 24 hours of data: 153 with open('24hrData.csv', 'wt') as f: 154 csv_writer = csv.writer(f, delimiter=',', quoting=csv.QUOTE_NONNUMERIC) 155 csv_writer.writerow(dist_array) 156 f.close() 157 158 159 # Midnight posting of th days stats: 160 if (t.gmtime().tm_hour == 0): 161 162 week_array[c.weekday(t.gmtime().tm_year,t.gmtime().tm_mon,t.gmtime().tm_mday)-1] = np.sum(dist_array) 163 164 # Save daily data: 165 with open('WeekData.csv', 'wt') as f: 166 csv_writer = csv.writer(f, delimiter=',', quoting=csv.QUOTE_NONNUMERIC) 167 csv_writer.writerow(week_array) 168 f.close() 169 170 screenUpdate() 171 ser.write(b'r') # to reset Arduino counter 172 t.sleep(0.1) 173 ser.flushInput() 174 lastDistance = 0 175 176 177
Gerbil Exercise Wheel Monitor v2 (serial communication with Pi)
arduino
1// Gerbil exercise wheel monitor 2// by Stuart Bryant - 15-Apr-19 3// v2 - adds serial communication with Raspberry Pi 4 5// Include the library code: 6#include "Wire.h" 7#include "Adafruit_LiquidCrystal.h" 8 9// Connect via i2c, default address #0 (A0-A2 not jumpered): 10Adafruit_LiquidCrystal lcd(0); 11 12// Define LED pin: 13#define LED_PIN 13 14 15// Define IR sensor pin: 16#define IR_SENSOR 3 17 18// Define wheel diameter constant [mm]: 19#define Diameter 130 20 21// Variable for recording distance: 22float Distance = 0; 23 24// Define integer variables: 25int Counts = 0; // counts the number of times that the IR beam has been broken 26int n = 0; // counter for Header function 27int DistInt = 0; // rounded distance 28int pi = 0; // serial message from Pi 29 30// Define timing variables: 31float LastTrigger = 0.0; 32float Period = 0.0; 33float Speed = 0.0; 34float MaxSpeed = 0.0; 35float LastSpeed = 0.0; 36 37 38void setup() { 39 40 // Open serial monitor: 41 Serial.begin(9600); 42 //Serial.println("Gerbil monitor!"); 43 //Serial.println("Distance [m] | Speed [mph] | Max Speed [mph]"); 44 45 // set up the LCD's number of rows and columns: 46 lcd.begin(16, 2); 47 48 displayReset(); 49 50 // Setup the LED: 51 pinMode(LED_PIN,OUTPUT); 52 53 // Setup the IR sensor input with a pull-up resistor: 54 pinMode(IR_SENSOR,INPUT_PULLUP); 55 56 // Attach interrupt tp IR sensor pin: 57 attachInterrupt(digitalPinToInterrupt(IR_SENSOR),BeamBreak, FALLING); 58} 59 60 61 62void displayReset() { 63 // Print a reading description text to LCD: 64 lcd.clear(); 65 lcd.print("Meters"); 66 lcd.setCursor(0, 1); 67 lcd.print("Max mph"); 68} 69 70void BeamBreak() { 71 72 Counts++; 73 74 // Calculated distance in meters: 75 Distance = Diameter * 3.14 * Counts / 1000; 76 DistInt = Distance; 77 Period = millis() - LastTrigger; 78 Speed = Diameter / Period * 7.028; // pi x 1000ms x 2.23694 mph/ m/s 79 80 if (Speed - LastSpeed < 3) { // filters out false readings 81 82 LastSpeed = Speed; // updates max speed 83 if (Speed > MaxSpeed) { 84 MaxSpeed = Speed; 85 //Serial.println("M"); // disabled in v2 86 //delay(5); 87 //Serial.println(MaxSpeed); 88 } 89 90 // Print data to serial monitor: 91 //Serial.print(Distance); // disabled in v2 92 //Serial.print(" "); 93 //Serial.print(Speed); 94 //Serial.print(" "); 95 //Serial.println(MaxSpeed); 96 //Header(); 97 98 LastTrigger = millis(); 99 } 100} 101 102// Function for formatting the serial monitor output with headers: 103void Header() { 104 if (n > 4) { 105 Serial.println("Distance [m] | Speed [mph] | Max Speed [mph]"); 106 n = 0; 107 } 108 n++; 109} 110 111void loop() { 112 113 // Illuminate board LED each time IR beam is broken: 114 if (digitalRead(IR_SENSOR) == LOW) { 115 digitalWrite(LED_PIN, HIGH); 116 } 117 else 118 { 119 digitalWrite(LED_PIN, LOW); 120 } 121 122 if(Serial.available()>0){ 123 pi = Serial.read(); 124 if(pi == 115){ // if 's' recieved 125 Serial.println(MaxSpeed); 126 } 127 else if(pi == 100) { // if 'd' recieved 128 Serial.println(Distance); 129 } 130 else if(pi == 114) { // if 'r' recieved 131 Counts = 0; 132 DistInt = 0; 133 Distance = 0; 134 MaxSpeed = 0; 135 displayReset(); 136 } 137 else{ 138 Serial.println(pi); 139 } 140 141 } 142 143 // Print data to LCD: 144 lcd.setCursor(9, 0); 145 lcd.print(DistInt); 146 lcd.setCursor(9, 1); 147 lcd.print(MaxSpeed); 148} 149 150
Gerbil Exercise Wheel Monitor
arduino
Measuring the distance and speed of a Gerbil in an exercise wheel.
1// Gerbil exercise wheel monitor 2// by Stuart Bryant - 25-Feb-19 3 4// Include the library code: 5#include "Wire.h" 6#include "Adafruit_LiquidCrystal.h" 7 8// Connect via i2c, default address #0 (A0-A2 not jumpered): 9Adafruit_LiquidCrystal lcd(0); 10 11// Define LED pin: 12#define LED_PIN 13 13 14// Define IR sensor pin: 15#define IR_SENSOR 3 16 17// Define wheel diameter constant [mm]: 18#define Diameter 130 19 20// Variable for recording distance: 21float Distance = 0; 22 23// Define integer variables: 24int Counts = 0; // counts the number of times that the IR beam has been broken 25int n = 0; // counter for Header function 26int DistInt = 0; // rounded distance 27 28// Define timing variables: 29float LastTrigger = 0.0; 30float Period = 0.0; 31float Speed = 0.0; 32float MaxSpeed = 0.0; 33float LastSpeed = 0.0; 34 35 36void setup() { 37 38 // Open serial monitor: 39 Serial.begin(9600); 40 Serial.println("Gerbil monitor!"); 41 Serial.println("Distance [m] | Speed [mph] | Max Speed [mph]"); 42 43 // set up the LCD's number of rows and columns: 44 lcd.begin(16, 2); 45 // Print a text to LCD: 46 lcd.clear(); 47 lcd.print("Meters"); 48 lcd.setCursor(0, 1); 49 lcd.print("Max mph"); 50 51 // Setup the LED: 52 pinMode(LED_PIN,OUTPUT); 53 54 // Setup the IR sensor input with a pull-up resistor: 55 pinMode(IR_SENSOR,INPUT_PULLUP); 56 57 // Attach interrupt tp IR sensor pin: 58 attachInterrupt(digitalPinToInterrupt(IR_SENSOR),BeamBreak, FALLING); 59} 60 61 62void BeamBreak() { 63 64 Counts++; 65 66 // Calculated distance in meters: 67 Distance = Diameter * 3.14 * Counts / 1000; 68 DistInt = Distance; 69 Period = millis() - LastTrigger; 70 Speed = Diameter / Period * 7.028; // pi x 1000ms x 2.23694 mph/ m/s 71 72 if (Speed - LastSpeed < 3) { // filters out false readings 73 74 LastSpeed = Speed; // updates max speed 75 if (Speed > MaxSpeed) { 76 MaxSpeed = Speed; 77 } 78 79 // Print data to serial monitor: 80 Serial.print(Distance); 81 Serial.print(" "); 82 Serial.print(Speed); 83 Serial.print(" "); 84 Serial.println(MaxSpeed); 85 86 Header(); 87 LastTrigger = millis(); 88 } 89} 90 91// Function for formatting the serial monitor output with headers: 92void Header() { 93 if (n > 4) { 94 Serial.println("Distance [m] | Speed [mph] | Max Speed [mph]"); 95 n = 0; 96 } 97 n++; 98} 99 100void loop() { 101 102 // Illuminate board LED each time IR beam is broken: 103 if (digitalRead(IR_SENSOR) == LOW) { 104 digitalWrite(LED_PIN, HIGH); 105 } 106 else 107 { 108 digitalWrite(LED_PIN, LOW); 109 } 110 111 // Print data to LCD: 112 lcd.setCursor(9, 0); 113 lcd.print(DistInt); 114 lcd.setCursor(9, 1); 115 lcd.print(MaxSpeed); 116} 117
Inky pHAT Display of Gerbil Data
python
Code for Raspberry Pi
1# Inky pHAT display of gerbil data 2# by Stuart Bryant 15-Apr-19 3 4# Inky pHAT set-up: 5 6from inky import InkyPHAT 7import numpy as np 8import math 9import csv 10 11 12inky_display = InkyPHAT("yellow") 13inky_display.set_border(inky_display.YELLOW) 14 15# Time imports and set-up: 16import calendar as c 17import time as t 18import datetime as dt 19 20weekdays = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'] 21 22#Set-up serial connection to Arduino: 23import serial 24ser = serial.Serial('/dev/ttyACM0', 9600) # open serial port to Arduino 25ser.flushInput() # remove any data from the serial buffer 26 27# Import Python Image Library: 28from PIL import Image, ImageFont, ImageDraw 29 30# Create a new canvas to draw on: 31img = Image.open("/home/pi/GerbilProject/G6.png") 32draw = ImageDraw.Draw(img) 33 34# Font definitions: 35from font_fredoka_one import FredokaOne 36font = ImageFont.truetype(FredokaOne, 22) 37font2 = ImageFont.truetype("Piboto-Bold.ttf", 14) 38font3 = ImageFont.truetype("Piboto-Bold.ttf", 7) 39 40# Create array for storing hourly distance: 41dist_array = np.full(24,1) 42 43# Create array for storing daily distance: 44week_array = np.full(7,0) 45 46# Import previous 24 hours of data: 47with open('24hrData.csv', 'rt') as f: 48 csv_reader = csv.reader(f, quoting=csv.QUOTE_NONNUMERIC) 49 for line in csv_reader: 50 for n in range (0, 24): 51 dist_array[n] = line[n] 52f.close() 53 54# Import previous daily distances: 55with open('WeekData.csv', 'rt') as f: 56 csv_reader = csv.reader(f, quoting=csv.QUOTE_NONNUMERIC) 57 for line in csv_reader: 58 for n in range (0, 7): 59 week_array[n] = line[n] 60f.close() 61 62m = np.amax(dist_array) # maxiumum hourly distance 63maxSpeed = 0 # maximum speed variable 64 65 66def screenUpdate(): 67 # Create a new canvas to draw on 68 img = Image.open("/home/pi/GerbilProject/G6.png") 69 draw = ImageDraw.Draw(img) 70 71 # Title text: 72 title = "Snuggles & Gingy" 73 w, h = font.getsize(title) 74 x = (inky_display.WIDTH / 2) - (w / 2) 75 y = 7 76 draw.text((x,y), title, inky_display.YELLOW, font) 77 78 # Data lines: 79 textDay = yesterday() + "'s data:" 80 draw.text((8,40), textDay, inky_display.BLACK, font2) 81 82 textDistance ="Distance: " + str(np.sum(dist_array)) + "m" 83 draw.text((8,60), textDistance, inky_display.BLACK, font2) 84 85 textSpeed ="Max Speed: " + str(maxSpeed) + "mph" 86 draw.text((8,80), textSpeed, inky_display.BLACK, font2) 87 88 m = np.amax(dist_array) 89 # Draw histogram data: 90 for n in range (0, 24): 91 draw.line((129+n*2,60, 129+n*2,60-dist_array[n]/m*20), fill=1) 92 93 # Histogram axes: 94 draw.line((127,40, 127,62), fill=2) 95 draw.line((125,60, 175,60), fill=2) 96 97 # x-axis labels: 98 draw.text((121,62), "0", inky_display.BLACK, font3) 99 draw.text((146,62), "12", inky_display.BLACK, font3) 100 draw.text((170,62), "24", inky_display.BLACK, font3) 101 102 # Set image and display: 103 inky_display.set_image(img) 104 inky_display.show() 105 106def yesterday(): 107 yesterday = weekdays[c.weekday(t.gmtime().tm_year,t.gmtime().tm_mon,t.gmtime().tm_mday)-1] 108 return yesterday 109 110def ArduinoSerial(input): 111 ser.write(bytes(input.encode('ascii'))) 112 t.sleep(0.1) # wait for Arduino to respond 113 if(ser.inWaiting() >0): 114 output = "" 115 line = ser.readline() 116 l = len(line) 117 l = l - 2 118 for char in line: 119 output = output + chr(char) 120 outputFloat = float(output[:l]) 121 return outputFloat 122 123 124screenUpdate() 125 126 127step = 3600 128 129s = t.time() 130s = math.ceil(s/step)*step 131interval = step # one hour interval 132lastDistance = 0 133 134while 1: 135 if (t.time() > s): 136 distance = ArduinoSerial('d') 137 maxSpeed = ArduinoSerial('s') 138 139 deltaDistance = distance - lastDistance 140 lastDistance = distance 141 dist_array[t.gmtime().tm_hour-1] = deltaDistance 142 143 s = s + interval 144 145 print("###################################") 146 print("Time: "+str(t.gmtime().tm_hour)+":"+str(t.gmtime().tm_min)+":"+str(t.gmtime().tm_sec)) 147 print("Interval distance =",deltaDistance, "Total distance:", distance) 148 print("Max speed today: "+str(maxSpeed)) 149 print("Distance array (last 24 hours):") 150 print(dist_array) 151 152 # Save last 24 hours of data: 153 with open('24hrData.csv', 'wt') as f: 154 csv_writer = csv.writer(f, delimiter=',', quoting=csv.QUOTE_NONNUMERIC) 155 csv_writer.writerow(dist_array) 156 f.close() 157 158 159 # Midnight posting of th days stats: 160 if (t.gmtime().tm_hour == 0): 161 162 week_array[c.weekday(t.gmtime().tm_year,t.gmtime().tm_mon,t.gmtime().tm_mday)-1] = np.sum(dist_array) 163 164 # Save daily data: 165 with open('WeekData.csv', 'wt') as f: 166 csv_writer = csv.writer(f, delimiter=',', quoting=csv.QUOTE_NONNUMERIC) 167 csv_writer.writerow(week_array) 168 f.close() 169 170 screenUpdate() 171 ser.write(b'r') # to reset Arduino counter 172 t.sleep(0.1) 173 ser.flushInput() 174 lastDistance = 0 175 176 177
Comments
Only logged in users can leave comments
hackminster
0 Followers
•0 Projects
Table of contents
Intro
3
0