|
Post by Martin on Jan 31, 2013 22:54:12 GMT
Hi
Can I use an XBee to control an RC tractor without using a microcontroller? There are loads of outputs on it including a pwm output, could I just use it to control a servo?
|
|
|
Post by RC Tractor Guy on Feb 1, 2013 9:36:42 GMT
Its a good idea but I don't think the PWM output would work with a servo, I read somewhere before that they are used to give a voltage rather than a PWM at a set frequency and differing duty cycle. I think it somehow changes the frequency as well as the duty cycle in an effort to minimise noise so that the voltage through a low pass filter will be pretty much noiseless. I think thats the idea anyway.
Maybe if you were able to send a command from your controller at the right time to turn on and off a digital output on the XBee but your microcontroller would be so busy doing that it wouldn't be able to do anything else I think. The easiest way to do it I think is to just you an MCU.
|
|
tomek
New Member
Posts: 24
|
Post by tomek on Aug 26, 2015 6:48:56 GMT
Hi, I have a problem with my XBee communication. Basically there is a controller with Leonardo and tractor with Pro Mini. In the tractor I have a led blinking then command from controller is received. I have a synchronous transmission of three bytes every 4000 cycles of the Leonardo this means about 1 second. Because of that I have delay up to two seconds from moving a joystick to the reaction of the tractor. Is this a normal situation? Have you faced such a problem ?
|
|
|
Post by RC Tractor Guy on Aug 26, 2015 10:26:50 GMT
Hi tomek, I might be misunderstanding something why does it take a second to send the three bytes, are you doing that on purpose for testing? The leonardo is using a 16MHz clock I think and I don't think there is a differentiator so that is 16*10^6 cycles per second so if your code takes 4000 cycles it should send the three bytes 4000 times in a second right? I might be wrong it's been about four years since I tried to work out the cycles of an MCU and that was with PIC mciros so might be different.
I have seen this problem before when I was using delays in loops by accident or using delays during testing. Or another possibility is if you are using interrupts, maybe the data is coming too fast for the MCU to do anything except receive data so it would be slow to carry out normal commands.
If you could post your code it might be easier to figure out the problem.
|
|
tomek
New Member
Posts: 24
|
Post by tomek on Aug 26, 2015 15:23:16 GMT
controller:
#include <SendOnlySoftwareSerial.h>
int ValueX = 0; int ValueY = 0; int ValueXsend = 0; int ValueYsend = 0; int DiffX; int DiffY; int i;
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; //9560 byte ID2 = 0x35; byte ID3 = 0x36; byte ID4 = 0x30; 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() { // odczyt joystick int sensorValueX = analogRead(A1) + OffsetX; int sensorValueY = analogRead(A0) + OffsetY;
//uwzglednienie histerezy if (sensorValueX >= ValueX) { DiffX = sensorValueX - ValueX; if (DiffX > histereza_joystick){ ValueX = sensorValueX; // SendDataX = 1; zablokowane na czas walki z napedem } } else { DiffX = ValueX - sensorValueX; if (DiffX > histereza_joystick){ ValueX = sensorValueX; // SendDataX = 1; zablokowane na czas walki z napedem } } if (sensorValueY >= ValueY) { DiffY = sensorValueY - ValueY; if (DiffY > histereza_joystick){ ValueY = sensorValueY; SendDataY = 1; } } else { DiffY = ValueY - sensorValueY; if (DiffY > histereza_joystick){ ValueY = sensorValueY; SendDataY = 1; } } /****************************** obsluga włączników ******************************/
i = i+1; if (i>=4000) i=0; if (i < 50) { digitalWrite(7,LOW); //pierwsza linia digitalWrite(8,HIGH); digitalWrite(9,HIGH); if (digitalRead(10) == 0) bitSet(wlaczniki,0); //pozycyjne else bitClear(wlaczniki,0); if (digitalRead(11) == 0) bitSet(wlaczniki,1); //kier prawy // else bitClear(wlaczniki,1); if (digitalRead(12) == 0) bitSet(wlaczniki,2); // krotkie else bitClear(wlaczniki,2); if (digitalRead(13) == 0) bitSet(wlaczniki,3); // kier lewy // else bitClear(wlaczniki,3); } else if (i > 100 && i <150) { digitalWrite(7,HIGH); //druga linia digitalWrite(8,LOW); digitalWrite(9,HIGH); if (digitalRead(10) == 0) bitSet(wlaczniki,4); //awaryjne else bitClear(wlaczniki,4); if (digitalRead(11) == 0) bitSet(wlaczniki,5); //kabina przod else bitClear(wlaczniki,5); if (digitalRead(12) == 0) bitSet(wlaczniki,6); // kogut else bitClear(wlaczniki,6); if (digitalRead(13) == 0) bitSet(wlaczniki,7); // kab tyl else bitClear(wlaczniki,7); } else if (i > 200 && i <250) { digitalWrite(7,HIGH); //druga linia digitalWrite(8,HIGH); digitalWrite(9,LOW); if (digitalRead(10) == 0) bitSet(wlaczniki2,0); //awaryjne else bitClear(wlaczniki2,0); if (digitalRead(11) == 0) bitSet(wlaczniki2,1); //krotkie else bitClear(wlaczniki2,1); if (digitalRead(12) == 0) bitSet(wlaczniki2,2); // kabina_tył else bitClear(wlaczniki2,2); if (digitalRead(13) == 0) bitSet(wlaczniki2,3); // kogut else bitClear(wlaczniki2,3); bitClear(wlaczniki2,4); bitClear(wlaczniki2,5); bitClear(wlaczniki2,6); bitClear(wlaczniki2,7); } else {} if (ValueX > 400) bitClear(wlaczniki,3); if (ValueX < 200) bitClear(wlaczniki,1); /******************************* obsługa komunikacji ********************************/
dataOut[0] = ID1;
dataOut[1] = 0x42;
dataOut[2] = map(ValueY, 0, 670, 0x00, 0xFF); if (i==999){ ExternalSerial.write(dataOut,3); //do xbee
Serial.write(dataOut,3); Serial.println(ValueY); }
wlaczniki2Last = wlaczniki2; }
tractor:
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 dat4 = 0x00; // Stores received byte byte dat5 = 0x00; // Stores received byte byte dat6 = 0x00; // Stores received byte byte ID1 = 0x39; //9560 byte ID2 = 0x35; byte ID3 = 0x36; byte ID4 = 0x30; byte drive_max = 255; // but you can change these values if you need to //byte drive_min = 100; byte drive_min = 0; byte drive_center = 128;// The drive is generally going to be the same for all models //byte drive_center = 178; int move1 = 125; // Variable used to determine the motor direction int move2 = 0;
byte command_val = 0x00; // Stores the command value byte data_val = 0x00; // Stores the data value byte servo_val = 0x00; // Variable used to ensure data_val is between servo limits //int servo_val = 0; int data = 0; // Variable to indicate serial data is available
void setup() { // initialize serial: Serial.begin(38400); // reserve 200 bytes for the inputString: inputString.reserve(200); // XBee.begin(9600); pinMode(13, OUTPUT); pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(11, OUTPUT); pinMode(15, OUTPUT); }
void loop() { if (Serial.available()) { Serial.println("data available"); inputString=Serial.readString(); Serial.println(inputString); dat1=inputString[0]; dat2=inputString[1]; dat3=inputString[2]; odebrano = true; digitalWrite(13,HIGH); } if (dat1 == ID1){ // Confirm that the correct vehicle ID has been recieved
command_val = dat2; // Store the new command value data_val = dat3;
Serial.println("traktor rozpoznany"); } if (odebrano==true){ delay(10); odebrano = false; digitalWrite(13,LOW); } switch (command_val){ // Perform an action based on the recieved command case 0x00: { // No command exit command selection break; } case 0x42: // Drive command { Serial.println("komenda drive"); servo_val = map(data_val, 0x00, 0xFF, drive_min, drive_max); // scale the data value for use with the motor Serial.println(servo_val); Serial.println(drive_center); Serial.println(data_val); if (servo_val < (drive_center-10)){ // These if functions leave a buffer zone of 15 bits above and below the drive center value // // If less than the buffer create speed value which must be between 0 and 255 i.e. 1 byte
move2=map(servo_val,0,128,255,100); analogWrite(11,move2); // Set the PWM vlue on pin 5 to move the motor digitalWrite(3, HIGH); // Set the direction with pins 7 and 8 digitalWrite(2, LOW); } else if (servo_val > (drive_center+10)){
move2=map(servo_val,128,255,100,255);
analogWrite(11,move2); // Set the PWM vlue on pin 5 to move the motor digitalWrite(3, LOW); // Set the direction with pins 7 and 8 digitalWrite(2, HIGH); } else { // If within the buffer turn off the motor analogWrite(11,0); digitalWrite(2, LOW); // Set the direction with pins 7 and 8 digitalWrite(3, LOW); } break; } } }
|
|
|
Post by RC Tractor Guy on Aug 26, 2015 18:23:03 GMT
I think I see the problem but I could be wrong. Your entire code appears to loop 4000 times between sending data to the XBee. That would be fine except you carry out two analogreads during each loop and I think each analogread takes 100us to complete if I remember correctly (I once tried to make a Arduino based frequency counter). That would mean 4000 loops of both of those would be in the region of 0.8 seconds. Could that be the delay you are seeing? Simple test would be to put them in
if (i==25){ // odczyt joystick int sensorValueX = analogRead(A1) + OffsetX; int sensorValueY = analogRead(A0) + OffsetY; }
so they only run once in the 4000 loops and see if it does what you require then. Your 4000 loops should take 0.0042 seconds to complete then I think but I'm not 100% sure.
|
|