Home › Forums › EasyTransfer Library Support Forum › little problem with timing
- This topic has 5 replies, 2 voices, and was last updated 12 years, 2 months ago by Anonymous.
-
AuthorPosts
-
February 27, 2013 at 5:14 am #2162AnonymousInactive
I love the library so far, but I had a few questions. Can you use booleans, because I have tried setting my two unos up as master slave and having the master send boolean commands to the slave. The problem is that the slave only receives the first command in the list. ex.
struct SEND_DATA_STRUCTURE { //Send commands
boolean SCAN;
boolean FORWARD;
boolean STOP;
boolean REVERSE;
boolean LEFT;
boolean RIGHT;
};
The slave only will pick up SCAN, even if I have the master send SCAN = LOW; and FORWARD = HIGH; the slave still just executes SCAN. Any ideas?
February 27, 2013 at 12:52 pm #2163BillMemberI don’t know what could be wrong without looking at the rest of your code, but I do suggest a more efficient way to do what you are trying to do.
You are trying to send 6 boolean (yes/no) values, however the smallest unit of data in an AVR is a byte of 8 bits. So each boolean uses up a whole byte of data space. So to send 6 yes/no values you are using up 6 whole bytes or 48 bits of data. Instead, you could encode all of your boolean values into a single byte. Here’s an example:
//first create a naming to position address convention, this is just to make it easier for us
#define SCAN 0
#define FORWARD 1
#define STOP 2
#define REVERSE 3
#define LEFT 4
#define RIGHT 5//create a variable that will hold all the values.
byte commands;//When we want to set a value to 1 (true) we do this
bitSet(commands, FORWARD);
bitSet(commands, LEFT);//When we want to clear a value (set to 0, false) we do this
bitClear(commands, RIGHT);
bitClear(commands, SCAN);//When we want to act on the different values
if(bitRead(commands, FORWARD) == true)
Do Something;if(bitRead(commands, SCAN) == false)
Stop Something;So it looks a bit different but it is a much more efficient way to encode binary (on or off) information. Give it a try and see if it works out for you.
You could also set a value directly from a digital input pin like this:
bitWrite(commands, FORWARD, digitalRead(13));
That will set the FORWARD bit TRUE if pin 13 is HIGH or FALSE if the pin is LOW.
February 27, 2013 at 12:55 pm #2164BillMemberOops, forgot to show you how to send that. It’s simple:
struct SEND_DATA_STRUCTURE { //Send commands
byte commands;
};
And That’s it. 6 of the 8 bits in commands hold all your boolean values as 1s or 0s.
February 27, 2013 at 7:51 pm #2165AnonymousInactiveThanks Bill, I’ve started changing the code to your suggestion. I will test in a few. If it doesn’t work, I’ll copy all the code and hopefully Iv’e just made a stupid mistake.
February 27, 2013 at 10:14 pm #2166AnonymousInactiveI have gotten the code you suggested working the same as the old (had to change bitWrite(commands, FORWARD, digitalRead(13));
to
bitWrite(commDataOut.commands, FORWARD, digitalRead(13)); etc.
however, I’m still only getting the slave to execute the first command (scan). code follows. I’m sure its in the slave code, but i’m unsure how to write it. I cant use interupts(I dont think) because of timing. Should i use case statements? I’m unsure how to get it working. BTW the slave is actually a pololu 3pi base (ATMEGA328)
//MASTER
#include <SoftwareSerial.h>
#include <SoftEasyTransfer.h>
unsigned long start, finished, elapsed;
boolean working;
int baseElapsed;
//ULTRASONIC
int distance;
int shortestDistance = 999;
int lowerDeadZone = 4;
int upperDeadZone = 500;
int sensorAngle = 15;
int pulseTime;
int initPin = 19;
int echoPin = 18;
int averageAmount = 10;
int currentNumber = 0;
int totalRaw;
//COMMUNICATION
SoftwareSerial BrainS(10, 11);
SoftEasyTransfer CommunicationsOut, CommunicationsIn; //Objects set up
#define Scan 0
#define Forward 1
#define Stop 2
#define Reverse 3
#define Left 4
#define Right 5
#define Complete 6
#define TimeElapsed 7
//byte COMMANDS;
//byte FEEDBACK;
struct SEND_DATA_STRUCTURE { //Send commands
byte COMMANDS;
};
struct RECEIVE_DATA_STRUCTURE{ //Receive commands
byte FEEDBACK;
};
SEND_DATA_STRUCTURE commDataOut; //name command groups
RECEIVE_DATA_STRUCTURE commDataIn;
//MAPPING
//int MAP [100] [100];
void setup() {
pinMode (initPin, OUTPUT);
pinMode (echoPin, INPUT);
Serial.begin(9600);
BrainS.begin(9600);
CommunicationsIn.begin(details(commDataIn), &BrainS);
CommunicationsOut.begin(details(commDataOut), &BrainS);
delay (2000);
findClosestWall();
}
void loop() {
if (CommunicationsIn.receiveData()) {
if (bitRead(commDataIn.FEEDBACK, Complete) == true) {
Serial.println (“Complete!”);
bitClear(commDataIn.FEEDBACK, Complete);
}
// if (bitRead(FEEDBACK, TimeElapsed) == true) {
// Serial.print (“time elapsed: “);
// Serial.println (commDataIn.timeElapsed);
// baseElapsed = commDataIn.timeElapsed;
// commDataIn.TIMEELAPSED = LOW;
// }
}
}
void findClosestWall () {
findDistance();
if (working == false) {
Serial.println(commDataOut.COMMANDS, Scan);
bitSet(commDataOut.COMMANDS, Scan);
Serial.println(commDataOut.COMMANDS, Scan);
CommunicationsOut.sendData();
start = millis();
Serial.println(“scan”);
working = true;
}
while (working == true) { //while waiting for base to finish
findDistance();
if (distance < shortestDistance) { //update shortest distance and find time since start
shortestDistance = distance;
finished = millis();
}
if (CommunicationsIn.receiveData()) {
if (bitRead(commDataIn.FEEDBACK, Complete) == HIGH) {
bitClear(commDataIn.FEEDBACK, Complete);
working = false;
elapsed = finished – start; //calculate time to turn
Serial.println(“scan 1 complete”);
Serial.print(“Closest: “);
Serial.println(shortestDistance);
delay (500);
Serial.print(“Time to wall: “);
Serial.println(elapsed);
delay (1000);
Serial.println(“turning towards wall”);
bitSet(commDataOut.COMMANDS, Scan); //turn
CommunicationsOut.sendData();
start = millis();
delay (elapsed);
bitSet(commDataOut.COMMANDS, Stop); //stop after turning towards wall
CommunicationsOut.sendData();
finished = millis();
elapsed = finished – start;
Serial.print(“Stopped after: “);
Serial.println(elapsed);
delay (1000);
findDistance();
while (distance >= lowerDeadZone) {
findDistance();
bitSet(commDataOut.COMMANDS, Forward); //forward
CommunicationsOut.sendData();
Serial.print(“Distance to 0:”);
Serial.println(distance – lowerDeadZone);
}
if (distance <= lowerDeadZone) {
bitSet(commDataOut.COMMANDS, Stop); //stop
CommunicationsOut.sendData();
Serial.println(“found wall”);
delay (200);
}
Serial.println(“turn 180”);
bitSet(commDataOut.COMMANDS, Scan); //turn
CommunicationsOut.sendData();
delay(baseElapsed / 2);
bitSet(commDataOut.COMMANDS, Stop); //stop after turning away from wall
CommunicationsOut.sendData();
}
}
}
}
void findDistance () {
for (int x = 0; x < averageAmount; x++) {
digitalWrite (initPin, HIGH);
delayMicroseconds (10);
digitalWrite (initPin, LOW);
pulseTime = pulseIn (echoPin, HIGH);
distance = pulseTime/58;
while (distance <= -1 || distance > upperDeadZone) {
digitalWrite (initPin, HIGH);
delayMicroseconds (10);
digitalWrite (initPin, LOW);
pulseTime = pulseIn (echoPin, HIGH);
distance = pulseTime/58;
}
totalRaw += distance;
currentNumber ++;
delay (5);
if (currentNumber == 10) {
distance = totalRaw / averageAmount;
totalRaw = 0;
currentNumber = 0;
}
}
}
//SLAVE
#include <pololu/orangutan.h>
#include <OrangutanMotors.h>
#include <OrangutanLCD.h>
#include <SoftwareSerial.h>
#include <SoftEasyTransfer.h>
unsigned long start, finished, elapsed;
int scanTime = 840;
int turnTime = 200;
SoftwareSerial BaseS(0, 1);
SoftEasyTransfer CommunicationsIn, CommunicationsOut; //Objects set up
#define Scan 0
#define Forward 1
#define Stop 2
#define Reverse 3
#define Left 4
#define Right 5
#define Complete 6
#define TimeElapsed 7
//byte COMMANDS;
//byte FEEDBACK;
struct RECEIVE_DATA_STRUCTURE{ //Receive commands
byte COMMANDS;
};
struct SEND_DATA_STRUCTURE{ //Send commands
byte FEEDBACK;
};
RECEIVE_DATA_STRUCTURE commDataIn; //name command groups
SEND_DATA_STRUCTURE commDataOut;
void setup() {
BaseS.begin(9600);
CommunicationsIn.begin(details(commDataIn), &BaseS);
CommunicationsOut.begin(details(commDataOut), &BaseS);
}
void loop() {
// Recieve and process recieved command
if (CommunicationsIn.receiveData()) {
update:
if (bitRead(commDataIn.COMMANDS, Scan) == true) { //SCAN
OrangutanLCD::clear();
OrangutanLCD::print(“SCAN”);
start = millis();
OrangutanMotors::setSpeeds(80, -80);
while (millis() < start + scanTime) {
if (CommunicationsIn.receiveData()) {
goto update;
}
}
OrangutanMotors::setSpeeds(0, 0);
finished = millis();
elapsed = finished – start;
//commDataOut.TIMEELAPSED = HIGH;
//commDataOut.timeElapsed = elapsed;
bitSet(commDataOut.FEEDBACK, Complete);
CommunicationsOut.sendData();
OrangutanLCD::clear();
bitClear(commDataIn.COMMANDS, Scan);
}
else if (bitRead(commDataIn.COMMANDS, Forward) == true) { //FORWARD
OrangutanLCD::clear();
OrangutanLCD::print(“FORWARD”);
OrangutanMotors::setSpeeds(80, 80);
bitClear(commDataIn.COMMANDS, Forward);
}
else if (bitRead(commDataIn.COMMANDS, Stop) == true) { //STOP
OrangutanLCD::clear();
OrangutanLCD::print(“STOP”);
OrangutanMotors::setSpeeds(0, 0); //stop movement
bitClear(commDataIn.COMMANDS, Scan);
bitClear(commDataIn.COMMANDS, Forward);
bitClear(commDataIn.COMMANDS, Reverse);
bitClear(commDataIn.COMMANDS, Left);
bitClear(commDataIn.COMMANDS, Right);
bitSet(commDataOut.FEEDBACK, Complete);
CommunicationsOut.sendData();
bitClear(commDataIn.COMMANDS, Stop);
}
else if (bitRead(commDataIn.COMMANDS, Reverse) == true) { //REVERSE
OrangutanLCD::clear();
OrangutanLCD::print(“REVERSE”);
OrangutanMotors::setSpeeds(-80, -80);
}
else if (bitRead(commDataIn.COMMANDS, Left) == true) { //LEFT
OrangutanLCD::clear();
OrangutanLCD::print(“LEFT”);
start = millis();
OrangutanMotors::setSpeeds(-80, 80);
while (millis() < start + turnTime) {
if (CommunicationsIn.receiveData()) {
goto update;
}
}
OrangutanMotors::setSpeeds(0, 0);
bitSet(commDataOut.FEEDBACK, Complete);
CommunicationsOut.sendData();
OrangutanLCD::clear();
bitClear(commDataIn.COMMANDS, Left);
}
else if (bitRead(commDataIn.COMMANDS, Right) == true) { //RIGHT
OrangutanLCD::clear();
OrangutanLCD::print(“RIGHT”);
start = millis();
OrangutanMotors::setSpeeds(80, -80);
while (millis() < start + turnTime) {
if (CommunicationsIn.receiveData()) {
goto update;
}
}
OrangutanMotors::setSpeeds(0, 0);
bitSet(commDataOut.FEEDBACK, Complete);
CommunicationsOut.sendData();
OrangutanLCD::clear();
bitClear(commDataIn.COMMANDS, Right);
}
}
}
March 1, 2013 at 3:53 am #2167AnonymousInactiveI’ve solved my issue by converting the byte into an integer after the slave receives it, then sending it through a switch case. I have now gotten the base to do all the commands it is supposed to. This library is a lifesaver. I would have hated (and had started when I found SoftEasy) to write my own protocol. Thanks Bill
-
AuthorPosts
- You must be logged in to reply to this topic.