Zoe The Robot
Arduino code for Odometry board - Counts Pulses from sprocket teeth (Distance traveled). Calculates Pulses per second (Speed). Reads motor current using the arduino A/D converters.
===================================================================================================
// Zoe_Odometer = Pgm to read pulses from two hall effect sensors pointing at
// sprocket teeth for Zoe's main drive.
// 9-21-21 Added speed measuring
// 9-07-25 Added current measuring Odom_Speed_Cur.ino
// library code:
#include // Need WIRE to talk to serial port
#include // Need LiquidCrystal to talk to LCD display
LiquidCrystal lcd(12, 11, 4, 5, 6, 7); // Define LCD display pins RS,E,D4,D5,D6,D7
// Pins:
const int PinLED = 13;
const int PinReset = 8;
const int LeftAnalogPin = A6;
const int RightAnalogPin = A5;
// Varz:
volatile unsigned long CountLeft = 0;
volatile unsigned long CountRight = 0;
bool LEDOn = true;
bool PinResetValue = HIGH;
// Varz for Speed Measuring
volatile unsigned long PreviousLeft = 0;
volatile unsigned long PreviousRight = 0;
volatile unsigned long LatestLeft = 0;
volatile unsigned long LatestRight = 0;
unsigned long PPSLeft = 0;
unsigned long PPSRight = 0;
// Varz for current sensing
volatile int LeftIsensor; // 0-1023
volatile int RightIsensor;
int LeftCurrent;
int RightCurrent;
int NullRight;
int NullLeft;
// The setup function runs once when you press reset or power on the board
void setup() {
pinMode(PinReset, INPUT_PULLUP);
// Set up the serial port
Serial.begin(9600);
Wire.begin();
// Set up LCD as 16x2 type
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Zoe The Robot");
lcd.setCursor(0, 1);
lcd.print("Odometry");
delay(2000);
lcd.clear();
pinMode(PinLED, OUTPUT); // Built in LED
Serial.println("* Hard Reset");
// Choices are: RISING , LOW , FALLING , CHANGE
attachInterrupt(digitalPinToInterrupt(2), IncrRightISR, RISING); // function for creating external interrupts at pin2 on Rising (LOW to HIGH)
attachInterrupt(digitalPinToInterrupt(3), IncrLeftISR, RISING); // function for creating external interrupts at pin3 on Rising (LOW to HIGH)
// Get Null Current reading - When no motion
delay(1000);
NullLeft = Round(analogRead(LeftAnalogPin));
delay(1000);
NullRight = Round(analogRead(RightAnalogPin));
// Show the nulls for 5 seconds
lcd.setCursor(0, 0); // top line
lcd.print("NullLeft = ");
lcd.print(NullLeft);
//
lcd.setCursor(0, 1); // second line
lcd.print("NullRight = ");
lcd.print(NullRight);
//
delay(2000);
}
// The loop function runs over and over again forever
void loop() {
// Main Loop
LatestRight = CountRight;
LatestLeft = CountLeft;
// Calculate pulses per second
PPSRight = (LatestRight - PreviousRight) / 2;
PPSLeft = (LatestLeft - PreviousLeft) / 2;
// Get current reading
LeftIsensor = Round(analogRead(LeftAnalogPin));
RightIsensor = Round(analogRead(RightAnalogPin));
// Fix the current readings
LeftCurrent = LeftIsensor - NullLeft;
RightCurrent = RightIsensor - NullRight;
if (abs(LeftCurrent) < 10) {
LeftCurrent = 0;
}
if (abs(RightCurrent) < 10) {
RightCurrent = 0;
}
////////////////////////////////////////////////
// start with blank slate
lcd.clear();
// Display Right Count on LCD
lcd.setCursor(0, 0); // top line
lcd.print("R ");
lcd.print(LatestRight);
// Display Right Current on LCD
lcd.setCursor(9, 0); // top line
lcd.print(RightCurrent);
// Display Right Speed on LCD
lcd.setCursor(14, 0);
lcd.print(" ");
lcd.setCursor(14, 0);
lcd.print(PPSRight);
////////////////////////////////////////////
// Display left Count on LCD
lcd.setCursor(0, 1); // second line
lcd.print("L ");
lcd.print(LatestLeft);
// Display left Current on LCD
lcd.setCursor(9, 1); // second line
lcd.print(LeftCurrent);
// Display Left Speed on LCD
lcd.setCursor(14, 1);
lcd.print(" ");
lcd.setCursor(14, 1);
lcd.print(PPSLeft);
/////////////////////////////////////////
// Send Counts to serial port
Serial.print("R:"); // pulse count right
Serial.print(LatestRight);
Serial.print(" SR:");
Serial.print(PPSRight);
Serial.print(" IR:"); // IR = Current Right
Serial.print(RightCurrent);
////////////////////////////////////////
Serial.print(" L:"); // pulse count left
Serial.print(LatestLeft);
Serial.print(" SL:"); // speed left
Serial.print(PPSLeft);
Serial.print(" IL:"); // IL = Current Left
Serial.print(LeftCurrent);
////// for testing /////////////////
// Serial.print(" >>>>>> ");
// Serial.print("NullRight: ");
// Serial.print(NullRight);
// Serial.print(" NullLeft: ");
// Serial.print(NullLeft);
// Line Feed
Serial.println();
// Supposed to give me current, in amps
// (0.0732 * LeftIsensor)-37.2
// (0.0732 * RightIsensor)-37.2
delay(987); // CHG'D FROM 2000 987
PreviousLeft = LatestLeft;
PreviousRight = LatestRight;
// Toggle LED
LEDOn = !LEDOn;
if (LEDOn) {
digitalWrite(PinLED, HIGH);
} else {
digitalWrite(PinLED, LOW);
}
// Check an input pin for counter reset signal
PinResetValue = digitalRead(PinReset); // read the input pin
// Call CounterReset if PinReset goes low
if (PinResetValue == LOW) {
CounterReset();
Serial.println("* Pin Reset");
}
}
// End of loop
// This code executes if data is recvd by serial port
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// Call CounterReset if R received
if (inChar == 'R') {
Serial.println("* Serial Reset");
CounterReset();
}
}
}
void IncrRightISR() {
CountRight++;
}
void IncrLeftISR() {
CountLeft++;
}
void CounterReset() {
CountRight = 0;
CountLeft = 0;
PreviousLeft = 0;
PreviousRight = 0;
lcd.clear();
}
int Round(int In) {
int Result;
int Fudge = 1;
Result = (In / Fudge) * Fudge;
return Result;
}