I'm back!
Today, we are going to look at how to add a failsafe and make a program that communicates with the computer.
First a schematic.
This is the schematic for the failsafe controller. I put this inside a small box with a battery so I could carry it in my hand without cords. The XBee radio inside is paired to a Xbee on the robot, connected to the Serial2 port on the Mega. That step should be fairly simple. Now here is the code for the failsafe controller:
And here is the code for the Mega on-board the robot:
This sets the failsafe such that, when the failsafe is activated, the led on the controller goes on. The failsafe can be activated one of two ways:
1. The Mega doesn't hasn't received a command in the past 500ms.
2. The button on the controller was pushed.
When the failsafe deactivates, the robot stops, and the LED will go off.
That's all for now!
Today, we are going to look at how to add a failsafe and make a program that communicates with the computer.
First a schematic.
This is the schematic for the failsafe controller. I put this inside a small box with a battery so I could carry it in my hand without cords. The XBee radio inside is paired to a Xbee on the robot, connected to the Serial2 port on the Mega. That step should be fairly simple. Now here is the code for the failsafe controller:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************************************** | |
ArduinoFailsafe.ino | |
Created September 17, 2016 | |
Adapted from the State Change Example by Tom Igoe | |
which was released into the public domain | |
Modified By: thecentralthinkingunit.blogspot.com | |
Released into the public domain | |
Purpose: | |
This program acts as a failsafe for the robot. | |
It sends 0xFF to a serial device(Xbee) when the button is pressed. | |
It also lights and LED when activated. | |
******************************************/ | |
#include <SoftwareSerial.h> | |
SoftwareSerial xbee = SoftwareSerial(2, 3);//Rx, Tx | |
// this constant won't change: | |
const int buttonPin = 7; // the pin that the pushbutton is attached to | |
const int ledPin = 10; // the pin that the LED is attached to | |
// Variables will change: | |
int buttonPushCounter = 0; // counter for the number of button presses | |
int buttonState = 0; // current state of the button | |
int lastButtonState = 0; // previous state of the button | |
void setup() { | |
// initialize the button pin as a input: | |
pinMode(buttonPin, INPUT_PULLUP); | |
// initialize the LED as an output: | |
pinMode(ledPin, OUTPUT); | |
// initialize serial communication: | |
Serial.begin(9600); | |
xbee.begin(9600); | |
} | |
void loop() { | |
// read the pushbutton input pin: | |
buttonState = digitalRead(buttonPin); | |
if(xbee.available() > 0 && xbee.read() == 0xAA && buttonPushCounter % 2 == 1){ | |
buttonPushCounter += 1; | |
} | |
// compare the buttonState to its previous state | |
if (buttonState != lastButtonState) { | |
// if the state has changed, increment the counter | |
if (buttonState == HIGH) { | |
// if the current state is HIGH then the button | |
// wend from off to on: | |
buttonPushCounter++; | |
Serial.println("on"); | |
Serial.print("number of button pushes: "); | |
Serial.println(buttonPushCounter); | |
} else { | |
// if the current state is LOW then the button | |
// wend from on to off: | |
Serial.println("off"); | |
} | |
// Delay a little bit to avoid bouncing | |
delay(50); | |
} | |
// save the current state as the last state, | |
//for next time through the loop | |
lastButtonState = buttonState; | |
// turns on the LED every other button push by | |
// checking the modulo of the button push counter. | |
// the modulo function gives you the remainder of | |
// the division of two numbers: | |
if (buttonPushCounter % 2 == 0) { | |
digitalWrite(ledPin, HIGH); | |
xbee.write(0xFF); | |
delay(50); | |
} else { | |
digitalWrite(ledPin, LOW); | |
} | |
} |
And here is the code for the Mega on-board the robot:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************************************** | |
* ArduinoToPython.ino | |
* Created September 16, 2016 | |
* Author: thecentralthinkingunit.blogspot.com | |
* Purpose: | |
* This program establishes a basic one way serial communications protocol. | |
* The computer sends the byte 0x41 to begin a packet. | |
* Then it sends two bytes, the first for the linear and the second for the linear. They must have a range from 0x00 to 0xB4(0-180 decimal) | |
* There is nothing to end a packet. This may be a good feature to add in the future. | |
******************************************/ | |
//#define DEBUG // Uncomment this line to enable serial debugging of the servo outputs. | |
#include <Servo.h>// Import the Servo library | |
/* Initialize two constant ints to hold the | |
pin numbers for the two channels*/ | |
const int angularServoPin = 48;//Black wire | |
const int linearServoPin = 52;//Blue wire | |
Servo angularServo;//Create servo objects for the two channels | |
Servo linearServo; | |
boolean failsafe = false;//Is the system in failsafe mode? | |
byte linear = 0x5A;//Variable to hold the current motor positions. | |
byte angular = 0x5A; | |
long timeSinceR = 0; | |
boolean firstTimeout = true; | |
long lastRecFailsafe = 0; | |
boolean firstFailsafeDisable = true;//Variable that assists with stopping the motors after leaving failsafe. | |
void processIncomingCommands() | |
{ | |
if(Serial.available() > 0) | |
{ | |
byte b = Serial.read(); | |
if(b == 0x41)//If the received byte is the starting flag. | |
{ | |
delay(25);//Sleep to wait for the next two bytes to get into the buffer. | |
linear = Serial.read(); | |
angular = Serial.read(); | |
timeSinceR = millis(); | |
} | |
} | |
} | |
void setup() // This function run once at start | |
{ | |
angularServo.attach(angularServoPin);// associate the servo object with the pin | |
linearServo.attach(linearServoPin); | |
angularServo.write(90);// set the angle of the servo to 90 degrees | |
linearServo.write(90); | |
Serial2.begin(9600); | |
Serial.begin(9600); | |
#ifdef DEBUG | |
pinMode(13, OUTPUT); | |
#endif | |
} | |
void loop() //Runs continuously after start | |
{ | |
processIncomingCommands(); | |
#ifdef DEBUG | |
Serial.print("Values: L: "); | |
Serial.print(constrain(int(linear), 0, 180)); | |
Serial.print(" A: "); | |
Serial.println(constrain(int(angular), 0, 180)); | |
#endif | |
if(millis() > timeSinceR + 500){ | |
if(firstTimeout == true){ | |
Serial2.write(0xAA); | |
failsafe = true; | |
firstTimeout = false; | |
} | |
}else{ | |
firstTimeout = true; | |
} | |
if(Serial2.available() > 0 && Serial2.read() == 0xFF){ | |
lastRecFailsafe = millis(); | |
failsafe = true; | |
firstFailsafeDisable = true; | |
} | |
if(millis() > lastRecFailsafe + 100){ | |
failsafe = false; | |
if(firstFailsafeDisable){ | |
firstFailsafeDisable = false; | |
linear = 0; | |
angular = 0; | |
} | |
} | |
if(failsafe){ | |
linearServo.write(90); | |
angularServo.write(90); | |
}else{ | |
linearServo.write(constrain(int(linear), 0, 180)); | |
angularServo.write(constrain(int(angular), 0, 180)); | |
} | |
} |
This sets the failsafe such that, when the failsafe is activated, the led on the controller goes on. The failsafe can be activated one of two ways:
1. The Mega doesn't hasn't received a command in the past 500ms.
2. The button on the controller was pushed.
When the failsafe deactivates, the robot stops, and the LED will go off.
That's all for now!
Comments
Post a Comment