Leonardo and XBee based RC controller

Viewing 14 posts - 1 through 14 (of 14 total)
  • Author
    Posts
  • #1134
    Tomek
    Participant

    As there is a new forum, I decided to move my topic here.
    for some time I cannot figure out why, but I have such a problem. There is a strange delay between controller and tractor.

    When I move joystick from centre to max forward, the weels are speeding up in two – three steps and those steps are related to the packets received by the microcontroller (the time is same to green led blnking)

    The controller code is:

    #include <SendOnlySoftwareSerial.h>

    int ValueX = 0;
    int ValueY = 0;
    int ValueXsend = 0;
    int ValueYsend = 0;
    int DiffX;
    int DiffY;
    int i;
    int sensorValueX = 0;
    int sensorValueY = 0;
    const int histereza_joystick = 1; //bylo 20
    const int OffsetX = 0;
    const int OffsetY = 0;
    boolean SendDataX; //*****************88 skończyć wysyłanie jak będzie komunikacja
    boolean SendDataY;
    byte wlaczniki = 0;
    byte wlacznikiLast = 0;
    byte wlaczniki2 = 0;
    byte wlaczniki2Last = 0;
    byte ID1 = 0x39; //9
    byte commandOut;
    byte valueOut;
    byte dataOut[6];

    SendOnlySoftwareSerial ExternalSerial(1);

    void setup() {
    // initialize serial communication at 9600 bits per second:
    ExternalSerial.begin(38400);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(10, INPUT_PULLUP); // kierunek lewy, prawy
    pinMode(11, INPUT_PULLUP); // pozycyjne, krótkie
    pinMode(12, INPUT_PULLUP); // kabina przód, tył
    pinMode(13, INPUT_PULLUP); // awaryjne, kogut
    }

    void loop() {
    i = i+1;
    if (i>=4000) i=0;

    //if (i==25) {
    // odczyt joystick
    sensorValueX = analogRead(A1) + OffsetX;
    sensorValueY = analogRead(A0) + OffsetY;
    // }
    //uwzglednienie histerezy
    if (sensorValueX >= ValueX) {
    DiffX = sensorValueX – ValueX;
    if (DiffX > histereza_joystick){
    ValueX = sensorValueX;
    }
    }
    else {
    DiffX = ValueX – sensorValueX;
    if (DiffX > histereza_joystick){
    ValueX = sensorValueX;
    }
    }

    if (sensorValueY >= ValueY) {
    DiffY = sensorValueY – ValueY;
    ValueY = sensorValueY;

    }
    else {
    DiffY = ValueY – sensorValueY;
    ValueY = sensorValueY;
    }

    /****************************** obsluga włączników ******************************/
    //check prog before 09 2015

    /******************************* obsługa komunikacji ********************************/
    dataOut[0] = ID1;
    dataOut[1] = 0x42;
    dataOut[2] = map(ValueY, 0, 670, 0x00, 0xFF);
    if (i==99){
    ExternalSerial.write(dataOut,3); //do xbee
    // Serial.write(dataOut,6); //do monitora

    Serial.write(dataOut,3);
    Serial.println(ValueY);
    }
    }

    And tractor code is:

    String inputString = “”; // a string to hold incoming data
    boolean stringComplete = false; // whether the string is complete
    boolean odebrano = false;
    byte dat1 = 0x00; // Stores received byte
    byte dat2 = 0x00; // Stores received byte
    byte dat3 = 0x00; // Stores received byte
    byte ID1 = 0x39; //9560
    byte drive_max = 255; // but you can change these values if you need to
    byte drive_min = 0;
    byte drive_center = 128;
    int move2 = 100;
    byte command_val = 0x00; // Stores the command value
    byte data_val = 0x7F; // Stores the data value
    int servo_val = 128; // Variable used to ensure data_val is between servo limits
    int servo_val2 = 128;
    int data = 0; // Variable to indicate serial data is available
    int i;
    int j = 0;
    const int leftana=11;
    const int connled=13;
    const int motorcon1=2;
    const int motorcon2=3;

    void setup() {
    // initialize serial:
    Serial.begin(38400);
    inputString.reserve(3);
    pinMode(13, OUTPUT);
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(11, OUTPUT);
    pinMode(15, OUTPUT);
    }

    void loop() {
    i = i+1;
    if (i>=10) i=0;
    // j = i / 10;
    if (dat1 == ID1){ // Confirm that the correct vehicle ID has been recieved
    command_val = dat2; // Store the new command value
    data_val = dat3;
    }

    if (odebrano==true && i==1){
    odebrano = false;
    digitalWrite(connled,LOW);
    }
    servo_val = map(data_val, 0x00, 0xFF, drive_min, drive_max); // scale the data value for use with the motor

    if (servo_val2 > servo_val && i==1) servo_val2=servo_val2-1;
    if (servo_val2 < servo_val && i==1) servo_val2=servo_val2+1;

    if (servo_val2 < (drive_center-10)){ // These if functions leave a buffer zone of 15 bits above and below the drive center value
    move2=map(servo_val2,0,128,255,100);
    digitalWrite(motorcon2, HIGH); // Set the direction with pins 7 and 8
    digitalWrite(motorcon1, LOW);
    }
    else if (servo_val2 > (drive_center+10)){
    move2=map(servo_val2,128,255,100,255);
    digitalWrite(motorcon2, LOW); // Set the direction with pins 7 and 8
    digitalWrite(motorcon1, HIGH);
    }
    else { // If within the buffer turn off the motor
    move2=100;
    digitalWrite(motorcon2, LOW); // Set the direction with pins 7 and 8
    digitalWrite(motorcon1, LOW);
    }
    analogWrite(leftana,move2);

    if (Serial.available()) {
    inputString=Serial.readString();
    dat1=inputString[0];
    dat2=inputString[1];
    dat3=inputString[2];
    odebrano = true;
    digitalWrite(connled,HIGH);
    }
    }

    Some time ago I was told by RC Tractor Guy to add if loop for analog reading, but with that modification it is not working at all.
    I have changed all analog write and digital write commands, no now there is a constant integer instead of numerical port number. I have also tried to disable buffer in the xbee and send all the data immediately, but nothing has changed.

    Any ideas?

    #1135
    Tomek
    Participant

    #1161
    RC Tractor Guy
    Keymaster

    That is a tricky one. Does it make sense to you that it didn’t work at all with the analogRead in the if loop? I mean you take a reading at i=25 and send at i=99 then why did you not see a change? You are clearly a better programmer than me, I’ve no clue of actual c or c++ so I don’t 100% follow your code unfortunately.

    Have you tried hooking the receive XBee to your computer and seeing how fast the data is arriving and whether it is what you would expect? Just to be sure the delay is in the controller code.

    Your 4WD is just awesome, every video I think it is so cool. I can’t wait to see it in action.

    #1199
    Tomek
    Participant

    After connecting xbee to the computer I was able to speed up sending up to one time per 50 cycles and serial data monitor was displaying correct packets. Probably it is possible to do that faster, but no need to. Transmitter is working correctly,
    I have replaced XBees with wires and it was working in the same way. This is not a XBee issue
    I have modified code a lot to make it simpler:

    void setup() {
      // initialize serial:
      Serial.begin(115200);
      inputString.reserve(3);
      pinMode(13, OUTPUT);
      pinMode(2, OUTPUT);      
      pinMode(3, OUTPUT);  
      pinMode(11, OUTPUT);    
      pinMode(15, OUTPUT);   
    }
    
    void loop() { 
    servo_val = map(data_val, 0x00, 0xFF, drive_min, drive_max);     // scale the data value for use with the motor 
    servo_val2=servo_val;
    
    if (servo_val2 > idle_high){
      move2=map(servo_val2,128,255,100,255);
      digitalWrite(motorcon2, LOW);               // Set the direction with pins 7 and 8
      digitalWrite(motorcon1, HIGH);
      }
     else {          // If within the buffer turn off the motor
      move2=100;
      digitalWrite(motorcon2, LOW);               // Set the direction with pins 7 and 8
      digitalWrite(motorcon1, LOW);
      }
      
     while (Serial.available()) {   
      inputString=Serial.readString();
      dat1=inputString[0];
      dat2=inputString[1];
      data_val=inputString[2];
     }    
    }

    There was no change after that either.

    I think the issue is related to serial buffer overflow, difference between speed of Leonardo and ProMini 3,3V or I need to change the way I read serial data to look for beginning of the packet.

    #1200
    Tomek
    Participant

    I have finally found the problem. Instead of this:

    while (Serial.available()) {   
      inputString=Serial.readString();
      dat1=inputString[0];
      dat2=inputString[1];
      data_val=inputString[2];
     }

    I have now this:

    while(Serial.available() > 0)
      {
        char inChar = Serial.read();
        if(inChar == SOP)
        {
           index = 0;
           inData[index] = '\0';
           started = true;
           ended = false;
        }
        else if(index == 3)
        {
           ended = true;
           break;
        }
        else
        {
          if(index < 79)
          {
            inData[index] = inChar;
            index++;
            inData[index] = '\0';
          }
        }
      }
    
      // We are here either because all pending serial
      // data has been read OR because an end of
      // packet marker arrived. Which is it?
      if(started && ended)
      {
        // The end of packet marker arrived. Process the packet
    
        // Reset for the next packet
        started = false;
        ended = false;
        index = 0;
        inData[index] = '\0';
      }
    
      data_val=inData[1];

    So I look for begining of the packet starting with char 9 length 3 chars and it is working well and fast. Also baudrate 9600 is enough.

    #1201
    RC Tractor Guy
    Keymaster

    That’s great news, I never would have caught that problem 🙂

    Have you much left to add to the model or just squeezing the components into the model now?

    #1202
    Tomek
    Participant

    My happiness came too early. There is no delay now, but one digital output to motor driver is blinking, and I have no idea why.
    I want to add all the lights and servo for rear attacher. Most likely it will take next half a year.

    #1203
    RC Tractor Guy
    Keymaster

    That is very strange alright, I can’t think of anything to help. I had taught maybe a library interfering or an interrupt but it doesn’t look like you’re using any of those. It can’t be a power problem because your video clearly shows the tractor working fine previously with the delay issue so I really don’t know. Maybe check if servo_val2 is changing for some reason but I don’t see why it should be.

    Sounds like you’ve a low to do alright, hopefully that all goes smoothly.

    #1204
    Tomek
    Participant

    It was a problem with:
    data_val=inData[1];
    After adding condition to do that if inData[1]!=0 it works fine.

    After connecting steering mechanism

    I have made such a movie:

    #1206
    RC Tractor Guy
    Keymaster

    That looks great, it moves at a really nice speed and it is a lot quieter than my model with the Tamiya gearbox. It’s a really nice job.

    #1209
    Tomek
    Participant

    I think it is a little bit too low. It is ok for a fieldwork, but for a transport it is slow. Also servo has not enough power when it is connected to 3,3 or even 5V power supply. I need to buy 6V power supply and check how the servo will work with that and control signal from arduino 3,3V. If it will be ok, I will change motors to 6V 100RPM.

    #1210
    RC Tractor Guy
    Keymaster

    That’s a pity about the servo, it would take a strong servo to slide all those wheels around. I have my rear wheels free wheeling so it is pretty easy to turn but I don’t have anywhere near your pulling power.

    What voltage and rpm are you currently using?

    #1211
    Tomek
    Participant

    I am thinking about Hitec HS-5085MG but it is quite expensive, so maybe I will look for something else. I am using 3v 50RPM motors.

    #1212
    RC Tractor Guy
    Keymaster

    You don’t have individual control of each motor do you? Maybe you could slow one side down as you steer or something.

    Also I’d say you could up the voltage of the motor you have to 5V and see if that was fast enough. I checked the serial number on an N20 motor I had before and the voltage was rated for 1.5 – 6V but was sold as 30rpm at 3volts or something like that.

Viewing 14 posts - 1 through 14 (of 14 total)

You must be logged in to reply to this topic.