Putting robotics at your service™

Free shipping on orders over $200

ArduinoFio/xbee +wii-chuck code > skid steering algorithm

Print view Share :
Previous topicNext topic

Page 1 of 2 [ 27 posts ]

1, 2
Rookie ( offline )
Posts: 17
Posted: 2011-11-17 05:16 
Hello, been lurking around here a few weeks. Some of you have some very cool projects. First a warning, I'm a hardware guy not a programmer so I have little knowledge of code, but I can cut and paste really good :mrgreen:
I am currently working on a remote control system for a differential drive rover with a ArduinoFio/2.4 series 1 xbee and Wii chuck on the transmitter end
and Arduino Uno/2.4 series 1 xbee for a receiver (servos for wheel motors right now).

Now, the problem, I have the TX end mixing the wii chuck x/y. Monitoring output of the TX on serial seems to be pretty responsive. Now my lacking ability of code work the receiver
lags horribly while trying to read the incoming packets. This is where I could use some help... (code is a mess of stuff I wrote and snippets I found online)

TX Code (some stuff is commented out for debugging and I am missing a LCD on the TX right now)
ETA: Code
Code:
/*
* WiiChuck-Fio Trasmitter //(with LCD output)
*
*
*
*/

#include <Wire.h>
//#include <LiquidCrystal.h>
#include "nunchuck_funcs.h"
#define debounce 10 // ms debounce
#define holdTime 2000 // ms hold period: how long to wait for press+hold event
#define DEBUG false // set to false to stop serial messages

int loop_cnt=0;
int loop_cnt2=0;
int throttle;
int ledPin0 = 9;
int ledPin1 = 10;
int ledPin2 = 11;
int ledPin3 = 13;
byte accx,accy,zbut,cbut,xjoy,yjoy,xraw, yraw;
//LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // LCD pins

int cbutVal = 0; // value read from button
int cbutLast = 0; // buffered value cbut previous state
int zbutVal = 0;
int zbutLast = 0;
long btnDnTime; // time the button was pressed down
long btnUpTime; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean ledVal0 = false; // state of LED 0
boolean ledVal1 = false; // state of LED 1
boolean ledVal2 = false; // state of LED 2
boolean ledVal3 = false; // state of LED 3




void setup() {

{
nunchuck_init(); // send the initilization handshake
pinMode(ledPin0, OUTPUT);
digitalWrite(ledPin0, ledVal0);
pinMode(ledPin1, OUTPUT);
digitalWrite(ledPin1, ledVal1);
pinMode(ledPin2, OUTPUT);
digitalWrite(ledPin2, ledVal2);
pinMode(ledPin3, OUTPUT);
digitalWrite(ledPin3, ledVal3);
Serial.begin(57600);

//lcd.begin(16, 2);
//lcd.print("WiiChuckServo ready"); // Print a message to the LCD.
//delay(10);*/
delay(10);
}
}

void loop()
{
{
{
{
if( loop_cnt > 100 ) { // every 100 msecs get new data
loop_cnt = 0;

nunchuck_get_data();

accx = nunchuck_accelx(); // ranges from approx 70 - 182 roll
accy = nunchuck_accely(); // ranges from approx 65 - 173 pitch
zbut = nunchuck_zbutton(); // 0 open 1 closed
cbut = nunchuck_cbutton(); // 0 open 1 closed
xraw = nunchuck_joyx(); // ranges from aprox 27 - 224 c=127-129 left - right
yraw = nunchuck_joyy(); // ranges from aprox 29 - 226 c=129-132 down - up

/*lcd.begin(16, 2);
lcd.print("X:");lcd.print((byte)valx,DEC);lcd.write(0xdf);
lcd.setCursor(6, 0);
lcd.print("Y:");lcd.print((byte)valy,DEC);lcd.write(0xdf);
lcd.setCursor(11, 0);if( cbut == HIGH){ lcd.print(" C");}
lcd.setCursor(13,0); if( zbut == HIGH){ lcd.print(" Z");}
lcd.setCursor(0, 1); if (ledVal1 == HIGH){lcd.print("Z Lights");}
lcd.setCursor(9, 1); if (ledVal2 == HIGH){lcd.print("Z Armed!");
}//End lcd out */
}
loop_cnt++;
delay(1); // delay came with WiiChuck script
}

{ //Start of X-Y mixing attempt
if( loop_cnt2 > 100 ){ //loop to prevent lag
loop_cnt2 = 0;
xjoy = map(xraw, 26, 225, 1, 180); // ranges from aprox 27 - 224 Left < c=127-129  >right
yjoy = map(yraw, 28, 227, 1, 180); //ranges from aprox 29 - 226 Down< c=129-132 >up
int rthrust = 0;
int lthrust = 0;

if(yraw > 143)//forward
{
rthrust = yjoy; // val 90-180
lthrust = yjoy;
if(xraw < 123)//left 90-1
{
lthrust = yjoy - map(xjoy, 90, 1, 20, 100);// math?
rthrust = yjoy;
}
else if(xraw > 133)// right 90-180
{
rthrust = yjoy - map(xjoy, 90, 180, 20, 100);//change to -map 1-90 or 20-100 for smaller turn increment
lthrust = yjoy; 
}
}

else if(yraw < 117)//reverse
{
rthrust = yjoy;
lthrust = yjoy; //val=1-90
if(xraw < 123)//left (fwd) 90-1
{
lthrust = yjoy + map(xjoy, 90, 1, 20, 100);
rthrust = yjoy;// reverse left
}
else if(xraw > 133)// right (fwd) 90-180
{
rthrust = yjoy + map(xjoy, 90, 180, 20, 100);// math?
lthrust = yjoy;
}
}
else //in Y deadband = zero turn
{
if(xraw < 123)//left 1-90
{
lthrust = map(xjoy, 90, 1, 90, 180);// math?
rthrust = xjoy; // full left & rev right
}
else if(xraw > 133)// right 90-180
{
lthrust = map(xjoy, 90, 180, 90, 1);// math?
rthrust = xjoy;// fwd right & reverse left
}
/* else
{
rthrust = 0;
lthrust = 0;
}*/
}

Serial.print("<");
Serial.print(lthrust, DEC);
Serial.print(":");
Serial.print(rthrust, DEC);
/*Serial.print(":");  // commented out for debug!!
Serial.print(accx, DEC);
Serial.print(":");
Serial.print(accy, DEC);
Serial.print(":");
Serial.print(ledVal0, DEC); //z press
Serial.print(":");
Serial.print(ledVal1, DEC); //z hold
Serial.print(":");
Serial.print(ledVal2, DEC); //c press
Serial.print(":");
Serial.print(ledVal3, DEC); //c hold   // commented out for debug!!
*/ Serial.println(">");
}
loop_cnt2++;
}
}
}


{
// Test for Cbut pressed and store the down time
if (cbut == HIGH && cbutLast == LOW && (millis() - btnUpTime) > long(debounce)) {
btnDnTime = millis();
}
cbutVal = cbut;// Read the state of the button
// Test for button release and store the up time
if (cbutVal == LOW && cbutLast == HIGH && (millis() - btnDnTime) > long(debounce)) {
if (ignoreUp == false) eventc1();
else ignoreUp = false;
btnUpTime = millis();
}
// Test for button held down for longer than the hold time
if (cbutVal == HIGH && (millis() - btnDnTime) > long(holdTime)) {
eventc2();
ignoreUp = true;
btnDnTime = millis();
}
cbutLast = cbutVal;//End of push hold C

// Test for Zbut pressed and store the down time
if (zbut == HIGH && zbutLast == LOW && (millis() - btnUpTime) > long(debounce)) {
btnDnTime = millis();
}
zbutVal = zbut;// Read the state of the button
// Test for button release and store the up time
if (zbutVal == LOW && zbutLast == HIGH && (millis() - btnDnTime) > long(debounce)) {
if (ignoreUp == false) eventz1();
else ignoreUp = false;
btnUpTime = millis();
}
// Test for button held down for longer than the hold time
if (zbutVal == HIGH && (millis() - btnDnTime) > long(holdTime)) {
eventz2();
ignoreUp = true;
btnDnTime = millis();
}
zbutLast = zbutVal;//End of push hold Z
}
}

// Events to trigger by click and press+hold Zbut

void eventz1(){ //Z press
ledVal0 = !ledVal0;
digitalWrite(ledPin0, ledVal0);
}
void eventz2(){ //Z hold
ledVal1 = !ledVal1;
digitalWrite(ledPin1, ledVal1);
}
void eventc1(){ //C press
ledVal2 = !ledVal2;
digitalWrite(ledPin2, ledVal2);
}
void eventc2(){ //C Hold
ledVal3 = !ledVal3;
digitalWrite(ledPin3, ledVal3);
}


RX Code (same some things commented out for trouble shooting or to try other things)
Code:
#include <Servo.h>
#include <LiquidCrystal.h>
#define BUFFER_MAX 10

int rthrust = 0;
int lthrust = 0;
int rthrust2;
//int ledPin2 = 8;
int ledPin3 = 13;
int loop_cnt0 = 0;
int loop_cnt1 = 0;
//int loop_cnt2 = 0;
Servo servoL;
Servo servoR;
//byte accx,accy,cbutp,cbuth,zbutp,zbuth; //Commented out for debug
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // LCD pins
byte counter = 0;
char buffer[BUFFER_MAX];

void setup() {
// pinMode(13, OUTPUT);//led //Commented out, I dont know why
Serial.begin(57600);
servoL.attach(10);//left
servoR.attach(9);//right
}

void loop() {
{
if(
 loop_cnt0 > 10 ){ //loop to prevent lag
loop_cnt0 = 0;
if (Serial.available()) {
char c = ((char)Serial.read());
if(
c == '<')
{
digitalWrite(13,HIGH);
counter = 0;
memset( buffer, 0, BUFFER_MAX);
}
else if(c == '>')
{
digitalWrite(13,LOW);
processMessage();
}
else
{
if(
counter == BUFFER_MAX)
counter = 0;

buffer[counter++] = c;
}
}
}
loop_cnt0++;
delay(1);

}
if(
 loop_cnt1 > 50 ){ //loop to prevent lag
loop_cnt1 = 0;
if (lthrust > 0) {
servoL.write(lthrust); }
else if(lthrust == 0){
servoL.write(90); }
if (rthrust > 0) {
rthrust2 = map(rthrust, 1, 180, 180, 1);
servoR.write(rthrust2); }
else if(rthrust == 0){
servoR.write(90); }
lcd.begin(16, 2);
lcd.setCursor(0, 0);lcd.print((byte)lthrust,DEC);lcd.write(0xdf);
lcd.setCursor(4, 0);lcd.print((byte)rthrust,DEC);lcd.write(0xdf);
//lcd.setCursor(9, 0);lcd.print((byte)loop_cnt0,DEC);
//lcd.setCursor(13,0);lcd.print((byte)counter,DEC);
//lcd.setCursor(0, 1);lcd.print(buffer);
//lcd.setCursor(9, 1);lcd.print(buffer);
}//End lcd out
loop_cnt1++;
delay(1);
}

void processMessage()//8 token- How does this section work, Is there something better?
{
// Serial.println(buffer);
// Serial.println(counter, DEC);
// if( loop_cnt2 > 20 ){ //loop to prevent lag
//loop_cnt2 = 0;
int count = 0;
int tokenCount = 0;
char tokenValue[3];
int tokenValues[3];
for(
int i=0; i<=counter; i++)
{
if(
buffer[i] == ':' || i == counter)
{
tokenValues[tokenCount++] = atoi(tokenValue);
count = 0;
memset(tokenValue, 0, 3);
}
else
{
tokenValue[count++] = buffer[i];
}
}
lthrust = tokenValues[0];
rthrust = tokenValues[1];
//accx = tokenValues[2]; //Commented out for debug
//accy = tokenValues[3];
//zbutp = tokenValues[4];
//zbuth = tokenValues[5];
//cbutp = tokenValues[6];
//cbuth = tokenValues[7]; 
//}
//loop_cnt2++;
delay(1);
}
 


Attachment:
File comment: Transmitter Code
WiichuckFIOv2.pde [7.04 KiB]
Downloaded 44 times
Attachment:
File comment: Receiver Code
ReceiverUno.pde [2.97 KiB]
Downloaded 35 times


Last edited by Wolf99 on 2012-05-07 01:41, edited 4 times in total.
User avatar
Guru ( offline )
Posts: 4905
Posted: 2011-11-17 10:51 
Hi and Welcome,

As for getting your code tags to work. My guess is that you have some option turned off in your profile. You can click on User Control Panel, than go to: Board Preferences, then click on edit posting defaults and my guess is something is turned off.

Since you mentioned you have been lurking around, you probably already know that I have been playing around with XBees for awhile and am currently also playing with two nun-chucks, so I will take a look. More on my Nunchuck/Arduino stuff up on the thread: viewtopic.php?f=21&t=7728
I have been somewhat side tracked on that thread lately as I picked up a 4D Systems touch screen and have been playing around with it and now I need to get back to adding the XBee onto this setup... But that is different subject.

Also more on my Arduino remote control up on thread: viewtopic.php?f=21&t=7422

So, again welcome.

Kurt


User avatar
Guru ( offline )
Posts: 4905
Posted: 2011-11-17 11:33 
I did a quick look and have a few questions/comments.
1) I am not sure how well the baud rate of 57600 works with Arduinos, running at 16mhz. May work fine if it configures for U2Xn = 1, but I see stuff in the hardware serial, that specifically turns this off for this baud rate... So I would personally try 38400. Or since you are using Hardware serial port you could try an XBee non standard baud rate of 62500. But you can not use this baud rate if you end up going to SoftwareSerial.

I am not sure about your need for your loop counts and delays... For example in your first loop, do you really need to add in the code for the counter and a delay. Or why not simply rely on the Serial.available() as it will tell you if there is any data that has been received from the XBee and it is quick as it simply has to check two values...

Also both parts/loops of your main have their own delay(1), so you are actually delaying at least twice...

If it were me, when I received a packet I would set a flag or the like. I would then check to see if the values has changed from the previous message, if so, I would update the servos and the LCD, otherwise I would not.

Hope that helps
Kurt


User avatar
Expert ( offline )
Posts: 750
Posted: 2011-11-17 12:22 
Wolf99 wrote:
[code==php]
but I cant get the code tags to work...
[/code]

The code tags are simply [ code ] and [ /code ] (without the spaces), you don't need to specify type of code or anything. If you hit the Code button it's a handy shortcut. But they'll never work if you've got BBCode disabled in your post options.

_________________
Beth
Lynxmotion, Inc
http://www.lynxmotion.com

THANKS I COULD HELP BRO


User avatar
Guru ( offline )
Posts: 4905
Posted: 2011-11-17 13:17 
Maybe something like:
Code:
#include <Servo.h>
#include <LiquidCrystal.h>
#define BUFFER_MAX 10

int rthrust = 0;
int lthrust = 0;
int rthrustCur = 0;        // know when something changed...
int lthrustCur = 0;

#define MAX_DELAY    500        // Half second...
unsigned long ulTimeLastMsg;    // when was our last message
unsigned long ulTime;

int rthrust2;
//int ledPin2 = 8;
int ledPin3 = 13;
//int loop_cnt2 = 0;
Servo servoL;
Servo servoR;
//byte accx,accy,cbutp,cbuth,zbutp,zbuth;
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // LCD pins
byte counter = 0;
char buffer[BUFFER_MAX];

void setup() {
    // pinMode(13, OUTPUT);//led
    Serial.begin(57600);
    servoL.attach(10);//left
    servoR.attach(9);//right
    ulTimeLastMsg = millis();    // remember when we receive  messages.
}

void loop() {
    if (Serial.available()) {
        char c = ((char)Serial.read());
        if(c == '<')
        {
            digitalWrite(13,HIGH);
            counter = 0;
            memset( buffer, 0, BUFFER_MAX);
        }
        else if(c == '>')
        {
            digitalWrite(13,LOW);
            processMessage();
            ulTimeLastMsg = millis();    // remember when we receive  messages.
        }
        else
        {
            if(counter == BUFFER_MAX)
                counter = 0;

            buffer[counter++] = c;
        }
    }

    ulTime = millis();
    if ((ulTimeLastMsg - ulTime) > MAX_DELAY) {
        // if we don't receive any valid message for a long time maybe we should set speeds to zero...
        rthrust = 0;
        lthrust = 0;
    }

    if ((rthrust != rthrustCur) || (lthrust != lthrustCur)) {
        rthrustCur = rthrust;    // save away new values...
        lthrustCur = lthrust;
       
        if (lthrust > 0) {
            servoL.write(lthrust);
        }
        else if(lthrust == 0){
            servoL.write(90);
        }
        if (rthrust > 0) {
            rthrust2 = map(rthrust, 1, 180, 180, 1);
            servoR.write(rthrust2);
        }
        else if(rthrust == 0){
            servoR.write(90);
        }
        lcd.begin(16, 2);
        lcd.setCursor(0, 0);
        lcd.print((byte)lthrust,DEC);
        lcd.write(0xdf);
        lcd.setCursor(4, 0);
        lcd.print((byte)rthrust,DEC);
        lcd.write(0xdf);
        //lcd.setCursor(9, 0);lcd.print((byte)loop_cnt0,DEC);
        //lcd.setCursor(13,0);lcd.print((byte)counter,DEC);
        //lcd.setCursor(0, 1);lcd.print(buffer);
        //lcd.setCursor(9, 1);lcd.print(buffer);
    }//End lcd out
}

void processMessage()//8 token
{
    //  Serial.println(buffer);
    //  Serial.println(counter, DEC);
    // if( loop_cnt2 > 20 ){ //loop to prevent lag
    //loop_cnt2 = 0;
    int count = 0;
    int tokenCount = 0;
    char tokenValue[3];
    int tokenValues[3];
    for(int i=0; i<=counter; i++)
    {
        if(buffer[i] == ':' || i == counter)
        {
            tokenValues[tokenCount++] = atoi(tokenValue);
            count = 0;
            memset(tokenValue, 0, 3);
        }
        else
        {
            tokenValue[count++] = buffer[i];
        }
    }
    lthrust = tokenValues[0];
    rthrust = tokenValues[1];
    //accx = tokenValues[2];
    //accy = tokenValues[3];
    //zbutp = tokenValues[4];
    //zbuth = tokenValues[5];
    //cbutp = tokenValues[6];
    //cbuth = tokenValues[7];
    //}
    //loop_cnt2++;
    delay(1);
}

/*if( tokenValues[3] > MAX_MAX )//Y axis ?
 {
 int servoValue = ((int)tokenValues[0]) - 180;
 if(servoValue < 0)
 servoValue *= -1;
 servoA.write(servoValue);
 }
 else
 {
 int angle = 90;
 if(tokenValues[2] < CENTER_MIN) //x axis
 angle = 180 - (tokenValues[2] - 400);
 if(tokenValues[2] > CENTER_MAX)
 angle = 600 - tokenValues[2];
 
 if(angle > 180)
 angle = 180;
 if(angle < 0)
 angle = 0;
 
 servoA.write(angle);
 }*/

Note: the above compiled on my machine, but I have not tried to run it... What I did was to not have any of your delay loops, but simply hard spin until you get a valid message, at which time I call your function. Then after that it checks to see if the drive values have changed, if so it calls of to your drive stuff. In addition I added a quick and dirty set of code to remember when the last message was received and if we have not received a message within so many milliseconds, it sets the speeds to 0...

Hope that helps
Kurt

Kurt


Rookie ( offline )
Posts: 17
Posted: 2011-11-17 13:19 
Snailkeeper (Admin) wrote:
Wolf99 wrote:
[code==php]
but I cant get the code tags to work...
[/code]

The code tags are simply [ code ] and [ /code ] (without the spaces), you don't need to specify type of code or anything. If you hit the Code button it's a handy shortcut. But they'll never work if you've got BBCode disabled in your post options.


I have BBCode turned on in my post options but its showing Options: BBCode is OFF on the side of the message editor...
ETA: and now its working :oops:


Rookie ( offline )
Posts: 17
Posted: 2011-11-17 13:49 
kurte wrote:
I did a quick look and have a few questions/comments.
1) I am not sure how well the baud rate of 57600 works with Arduinos, running at 16mhz. May work fine if it configures for U2Xn = 1, but I see stuff in the hardware serial, that specifically turns this off for this baud rate... So I would personally try 38400. Or since you are using Hardware serial port you could try an XBee non standard baud rate of 62500. But you can not use this baud rate if you end up going to SoftwareSerial.

I am not sure about your need for your loop counts and delays... For example in your first loop, do you really need to add in the code for the counter and a delay. Or why not simply rely on the Serial.available() as it will tell you if there is any data that has been received from the XBee and it is quick as it simply has to check two values...

Also both parts/loops of your main have their own delay(1), so you are actually delaying at least twice...

If it were me, when I received a packet I would set a flag or the like. I would then check to see if the values has changed from the previous message, if so, I would update the servos and the LCD, otherwise I would not.

Hope that helps
Kurt


Ok, when I went to post the code last night I was going to note a few things but didn't. I was using the loop counts to attempt to keep more cpu free for the receive part of the loop and to avoid using the delay call. Most of my code is cut and paste from other code snippets. I know I got the idea for the loop count from the wiichuckdemo script.
LCD is only in place on the rover for trouble shooting stuff right now (and because its 5vt vfd not so good for the Fio). And the arduino fio is the reason the baud rate is at 57600 for wireless updating of the code.

When I said I know "hardware" I should I probably worded it as I can build stuff :mrgreen: eg:fabricating chassis, control boxes, wiring stuff up. I don't know much about serial comms and what not. And there seems to be a big hole when it comes to googleing for info on remote controls of this sort...

One observation with my "original" code for the reciever end is that it was acting like the buffer(?) in the was getting backed logged so to speak, after about 5-10 sec of position data the pin 13 light would go from blinking to stuck solid and the control outputs would start to delay (lag) to the point where it would take 4-5 sec for the command from the joystick to make it to the servos.

Last note, with the tx/rx scripts/software one of my goals is to have access to both buttons (using the press/hold script) and x/y from both the joystick and the accelerometers. Right now I have that commented out on both ends because I think there was too much data for the arduino to decode (least with my poor coding attempt)


Rookie ( offline )
Posts: 17
Posted: 2011-11-17 14:06 
kurte wrote:
Maybe something like:
Code:
Snip~

Note: the above compiled on my machine, but I have not tried to run it... What I did was to not have any of your delay loops, but simply hard spin until you get a valid message, at which time I call your function. Then after that it checks to see if the drive values have changed, if so it calls of to your drive stuff. In addition I added a quick and dirty set of code to remember when the last message was received and if we have not received a message within so many milliseconds, it sets the speeds to 0...

Hope that helps
Kurt

Kurt


I'll give it a go on my prototype (which is only a piece of perf pcb with 2 servos hooked to it). And if there is a better way to do the data packets I'm all for suggestions. Only reason I am using the code I have now for the control packets is because its the only example of it that I could find after 3-4 hours spent on google that had enough info for me to get it to work.


User avatar
Guru ( offline )
Posts: 4905
Posted: 2011-11-17 14:19 
As I mentioned in my first response, I have been playing around with remote controls using Xbees for awhile now. At first mainly using Basic Atom Pro 28 boards. Recently I ported all of the stuff to the Arduino. There is lots of information up on the threads I mentioned as well as the main thread on my XBee work:
viewtopic.php?f=21&t=5447

In a nut shell, I am using handshaking between the two XBees, which involved things, like I went to packet mode instead of serial replacement mode. This way I receive actual XBee packets with checksums and lengths and the like.

2nd, I have my robot wanting data from the remote, to send a packet to it, saying I want it now... Only then does the remote send out the data. That way you are not having your buffers overrun...

Also with my code attempt, I would probably change it some more:
In Particular, I would probably change:
Code:
 if (Serial.available()) {

To:
Code:
    while(Serial.available()) {

That way you are grabbing as much data from the serial port as you can.

Also in serial replacement mode, I am not sure when the XBee on the sending side will decide to send out a packet of data. It may be only happen, when it has so many characters, or some timeout time, or maybe when <CR> is received...

Kurt


Rookie ( offline )
Posts: 17
Posted: 2011-11-17 14:46 
Yeah, thats the kind of info I am looking for, I know the code I am currently using work... but I knew there has to be a better way, I'll dig in to the thread you mention later this evening and see what I can learn. I would like to keep/get some info in this thread tho, at least to get the focus towards ways to get the data in/out of the arduino efficiently.

My ultimate project goal is to have 2 different differential drive bots to control (once I get the control software working reliable of course)
First chassis I am working on (in build process right now) is aprox 12inch long by 10 inch wide, H bridge motor control w/ 2 9.6 drill motors, 2 SLA batteries, plan to equip it with a raise-able arm w/ pan/tilt camera and light attached. Drive control via wiichuck x/y stick, arm via latching button+ x/y stick, pan/tilt via accelerometers, and light control via button.
Second planned chassis is a little bigger... (on paper only right now) looking at a 28hp gas motor running a hydraulic pump, 2 hydro wheel motors via electronic valving turning a tracked drive system and a mowing system also powered by the hydraulic loop.

Thanks for the help
I'll be back on later tonight with more questions I bet :)


Rookie ( offline )
Posts: 17
Posted: 2011-11-18 15:02 
Ok... Took a look at DIY_Remote-110922a.zip (from Arduino Mega based DIY Remote (XBee) thread)
I can now honestly say, I have no clue when it comes to coding...

kurte wrote:
Maybe something like:
Code:
~snip

Note: the above compiled on my machine, but I have not tried to run it... What I did was to not have any of your delay loops, but simply hard spin until you get a valid message, at which time I call your function. Then after that it checks to see if the drive values have changed, if so it calls of to your drive stuff. In addition I added a quick and dirty set of code to remember when the last message was received and if we have not received a message within so many milliseconds, it sets the speeds to 0...

Hope that helps
Kurt


Tried the code you posted, It works, sort of... it seems to be resetting the drive inputs to 0 between sending the 1-180 to the servos so they are just jittering for the most part (though in the right directions at least), I'll see if I can figure it out...
Tho I'm starting to think scrapping my current code is going to be needed.
If I go the xbee API route I think the FIO is out for the TX end because it becomes a royal PITA to pull the xbee every time you need to update the code on it, I'm thinking a arduino pro-mini or something of the sort on a custom breakout board w/ a xbee socket, li-ion charge/regulator circuit and usb w/ dip switches to select xbee/arduino programming would be the ticket (yeah... I dont know how to code but I etch my own circuit boards :mrgreen: )
Any help, suggestions or comments will be appreciated.

~Wolf


User avatar
Guru ( offline )
Posts: 4905
Posted: 2011-11-18 15:16 
Got to run, but yep I have avoided using digital pins 0,1 (hardware serial port) with XBees or other devices as it is also used by USB... So as you said pulling the chip every time would not be fun! I end up using an external holder for my XBee and on non-megas I try to use the New software Serial library, on Megas I use one of the other hardware serial port. For most of my Atmega based processors I am now using XBee adapters from Parallax as I have had some issues with the Sparkfun ones not working with some of the different boards (does not do voltage conversion of TX line and the high may not be high enough to register as high on the Atmega board... )

As for the code I posted, you may want to look at the timeout code. Also did you convert the if, to a while...

Kurt


User avatar
Guru ( offline )
Posts: 4118
Posted: 2011-11-18 15:36 
Kurt, what's your day job?

You seem to have much more time to play then I do!

Alan KM6VV

_________________
Visit:
http://groups.yahoo.com/group/SherlineCNC/
http://tech.groups.yahoo.com/group/HexapodRobotIK/


Rookie ( offline )
Posts: 17
Posted: 2011-11-18 17:12 
kurte wrote:
Got to run, but yep I have avoided using digital pins 0,1 (hardware serial port) with XBees or other devices as it is also used by USB... So as you said pulling the chip every time would not be fun! I end up using an external holder for my XBee and on non-megas I try to use the New software Serial library, on Megas I use one of the other hardware serial port. For most of my Atmega based processors I am now using XBee adapters from Parallax as I have had some issues with the Sparkfun ones not working with some of the different boards (does not do voltage conversion of TX line and the high may not be high enough to register as high on the Atmega board... )

As for the code I posted, you may want to look at the timeout code. Also did you convert the if, to a while...

Kurt


Yeah, the pro/con with the arduino fio board is the xbee header is made in to it, makes a nice one piece setup but you are stuck on d0,d1 for the io. It seemed like a good idea when I started laying out my project...
Anyways, I used the while(Serial.available) call, but I really dont think the timeout code is causing it... really I have no idea whats causing it, I have the TX sending at 20 loop count which seemed to be a bit overkill and over loaded(?) the buffer and caused what seemed to be a soft lock up of the loop after 3-4 secs of transmit, setting it to a 50 count seems to keep the lockup issue at bay but still having the problem with output kicking out the 0.
The more I mess with my attempt vs looking at the DIY remote code I think I can suck up the PITA of pulling the xbee off the fio a few dozen times if it means I'll have a working remote system.

Code:
/*ReceiverUno2 Code update 11/18/2011 14:10
**
**
**
*/

#include <Servo.h>
#include <LiquidCrystal.h>
#define BUFFER_MAX 10

int rthrust = 0;
int lthrust = 0;
int rthrustCur = 0;        // know when something changed...
int lthrustCur = 0;

#define MAX_DELAY    500        // Half second...
unsigned long ulTimeLastMsg;    // when was our last message
unsigned long ulTime;

int rthrust2;
//int ledPin2 = 8;
int ledPin3 = 13;
Servo servoL;
Servo servoR;
//byte accx,accy,cbutp,cbuth,zbutp,zbuth;
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // LCD pins
byte counter = 0;
char buffer[BUFFER_MAX];

void setup() {
 
    Serial.begin(57600);
    servoL.attach(10);//left
    servoR.attach(9);//right
    ulTimeLastMsg = millis();    // remember when we receive  messages.
}

void loop() {
   while(Serial.available()) {
        char c = ((char)Serial.read());
        if(c == '<')
        {
            digitalWrite(13,HIGH);
            counter = 0;
            memset( buffer, 0, BUFFER_MAX);
        }
        else if(c == '>')
        {
            digitalWrite(13,LOW);
            processMessage();
            ulTimeLastMsg = millis();    // remember when we receive  messages.
        }
        else
        {
            if(counter == BUFFER_MAX)
                counter = 0;

            buffer[counter++] = c;
        }
    }

    ulTime = millis();
    if ((ulTimeLastMsg - ulTime) > MAX_DELAY) {
        // if we don't receive any valid message for a long time maybe we should set speeds to zero...
        rthrust = 0;
        lthrust = 0;
    }

    if ((rthrust != rthrustCur) || (lthrust != lthrustCur)) {
        rthrustCur = rthrust;    // save away new values...
        lthrustCur = lthrust;
       
        if (lthrust > 0) {
            servoL.write(lthrust);
        }
        else if(lthrust == 0){
            servoL.write(90);
        }
        if (rthrust > 0) {
            rthrust2 = map(rthrust, 1, 180, 180, 1);
            servoR.write(rthrust2);
        }
        else if(rthrust == 0){
            servoR.write(90);
        }
        //LCD out for DEBUG
        lcd.begin(16, 2);
        lcd.setCursor(0, 0);
        lcd.print((byte)lthrust,DEC);
        lcd.write(0xdf);
        lcd.setCursor(4, 0);
        lcd.print((byte)rthrust,DEC);
        lcd.write(0xdf);
        //lcd.setCursor(9, 0);lcd.print((byte)loop_cnt0,DEC);
        //lcd.setCursor(13,0);lcd.print((byte)counter,DEC);
        //lcd.setCursor(0, 1);lcd.print(buffer);
        //lcd.setCursor(9, 1);lcd.print(buffer);
    }//End lcd out
}

void processMessage()//8 token
{
    int count = 0;
    int tokenCount = 0;
    char tokenValue[3];
    int tokenValues[3];
    for(int i=0; i<=counter; i++)
    {
        if(buffer[i] == ':' || i == counter)
        {
            tokenValues[tokenCount++] = atoi(tokenValue);
            count = 0;
            memset(tokenValue, 0, 3);
        }
        else
        {
            tokenValue[count++] = buffer[i];
        }
    }
    lthrust = tokenValues[0];
    rthrust = tokenValues[1];
    //accx = tokenValues[2];
    //accy = tokenValues[3];
    //zbutp = tokenValues[4];
    //zbuth = tokenValues[5];
    //cbutp = tokenValues[6];
    //cbuth = tokenValues[7];
    delay(1);
}


User avatar
Guru ( offline )
Posts: 4905
Posted: 2011-11-18 21:40 
Some of the things I would still look at include:

Maybe make your input buffer a bit larger as to make sure that you don't overflow and reset it.

Also look at your LCD calls. I have not use the LCD library, but my quick look at it shows that several of the commands have some large delays in it, especially ones like: lcd.begin(16,2). My guess is you should move this call into the Setup function and not every time you try to output to the LCD...

Kurt


1, 2

All times are UTC - 5 hours [ DST ]. It is currently 2014-09-17 23:36
Feedback Form
Feedback Form