Mein ferngesteuerter Roboter

Hallo liebe Diyer(Do it yourself-Bastler),

ich arbeite gerade hobbymäßig an meinem Roboter.

Mein Setup:

Roboter:

Heng-Long KV1 Metall Unterwanne
2x 12 Volt Motoren
Metall-Tracks
Monster Moto Shield
Arduino Mega 2560
Grove Base Mega Shield
Grove Xbee Carrier
Grove 10Dof IMU
Grove GPS
XBee Pro 10mW RPSMA - Series 2B (ZigBee Mesh) XBP24BZ7SIT-004J+ große Dipolare Antenne
2x 11,1 Volt Lipo 4500mah parallel geschaltet

Fernsteuerung:
Arudino Uno kompatibles Board
Seedstudio SD Shield 4.0 +16GB SD Card
Arduino 1602 LCD Keypad Shield (Buttons will ich später nutzen, um durch die Daten zu schalten, Z.B GPS, Höhe, Luftdruck, usw.)
Grove Xbee Carrier
XBee Pro 10mW RPSMA - Series 2B (ZigBee Mesh) XBP24BZ7SIT-004J+ große Dipolare Antenne
2 Grove Thumbsticks (1x für Steuerung, 1x für Geschwindigkeit)
11.1 Volt Lipo

Was ich damit vorhabe:
Ich will den Roboter per Fernsteuerung steuern, während der Roboter die GPS/IMU Daten auf das LCD der Fernsteuerung sendet und auf der SD Card speichert. Später sollen noch ein FPV Set und ein Greifarm dazukommen.

Allerdings will ich erstmal die Motoren zum Laufen kriegen bzw. ansteuern können.

Xbee Sender ist auf Coordinator AT (Baud 115200)
Xbee Empfänger ist auf Router AT eingestellt.(Baud 115200)

Mein Sender Sketch bis jetzt:

#define BRAKEVCC 0
#define CW   1
#define CCW  2
#define BRAKEGND 3
#define CS_THRESHOLD 100

int inApin[2] = {7, 4};  // INA: Clockwise input
int inBpin[2] = {8, 9}; // INB: Counter-clockwise input
int pwmpin[2] = {5, 6}; // PWM input
int cspin[2] = {2, 3}; // CS: Current sense ANALOG input
int enpin[2] = {0, 1}; // EN: Status of switches output (Analog pin)
int statpin = 13;
int speed = 0;

void setup()
{
Serial.begin(115200);
pinMode(statpin, OUTPUT);

// Initialize digital pins as outputs
for (int i=0; i<2; i++)
{
  pinMode(inApin[i], OUTPUT);
  pinMode(inBpin[i], OUTPUT);
  pinMode(pwmpin[i], OUTPUT);
}

// Initialize braked
for (int i=0; i<2; i++)
{
  digitalWrite(inApin[i], LOW);
  digitalWrite(inBpin[i], LOW);
}
}

Empfänger-Sketch:

/*----------------------------
pmw value has to be < 1023.
CCW=CounterClockwise
CW=ClockWise
-----------------------------*/
void loop()
{                            
 int sensorValue1 = analogRead(A3);
 int sensorValue2 = analogRead(A4);
 int sensorValue3 = analogRead(A1);
 int sensorValue4 = analogRead(A2);


if (sensorValue1 >550){
 Serial.println("Back");
 delay(1000);
 motorGo(0, CCW, speed);       //Motor1
 motorGo(1, CW,  speed);      //Motor2
}

if (sensorValue1 <470) {
 Serial.println("Front");
 delay(1000);
 motorGo(0, CW, speed);        //Motor1
 motorGo(1, CCW, speed);      //Motor2
}
if (sensorValue2 > 570) {
 Serial.println("Right");
 delay(1000);
 motorGo(0, CW, 100);        //Motor1
 motorGo(1, CW, 100);      //Motor2
}

if (sensorValue2 <470) {
 Serial.println("Left");
 delay(1000);
 motorGo(0, CCW, 100);      //Motor1
 motorGo(1, CCW, 100);      //Motor2
}

if ((analogRead(cspin[0]) < CS_THRESHOLD) && (analogRead(cspin[1]) < CS_THRESHOLD))
  digitalWrite(statpin, HIGH);
}

void motorOff(int motor)
{
// Initialize braked
for (int i=0; i<2; i++)
{
  digitalWrite(inApin[i], LOW);
  digitalWrite(inBpin[i], LOW);
}
analogWrite(pwmpin[motor], 0);
}

void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm)
{
if (motor <= 1)
{
  if (direct <=4)
  {
    // Set inA[motor]
    if (direct <=1)
      digitalWrite(inApin[motor], HIGH);
    else
      digitalWrite(inApin[motor], LOW);

    // Set inB[motor]
    if ((direct==0)||(direct==2))
      digitalWrite(inBpin[motor], HIGH);
    else
      digitalWrite(inBpin[motor], LOW);
    analogWrite(pwmpin[motor], pwm);
  }
}
}

Mein Empfänger Sketch:

void setup () {

Serial.begin (115200);
}


void loop () {
if (Serial.available() >0 {
Serial.write(Serial.read());

}
}

Die Joystick Bewegungen kann ich schon empfangen (Front,Back,usw) Wie schaffe ich es, dass er die Motoren auch ansteuert? Muss der Motor-Code im Empfänger sein?

Vielen Dank und Viele Grüße

Andreas

Hallo Andreas und willkommen im Forum!

Bitte packe Deine Sketche in code-Tags (links oben der Button </>), damit der Index i nicht als Umschalten nach kursiv (=italic) mißverstanden wird.

Zyr666:
Muss der Motor-Code im Empfänger sein?

Ja, da wo die Motoren werkeln beim Monster Moto Shield.

Danke Agmue!

So habe jetzt meine Codes angepasst:

Sender:

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:

int sensorValue1 = analogRead(A3);
  int sensorValue2 = analogRead(A4);
  int sensorValue3 = analogRead(A1);
  int sensorValue4 = analogRead(A2);

if (sensorValue1 >550){
  Serial.println("Back");
  Serial.print('B');
  delay(100); }

if (sensorValue1 <470) {
  Serial.println("Front");
  Serial.print('F');
  delay(100); }
  
if (sensorValue2 > 570) {
  Serial.println("Right");
  Serial.print('R');
  delay(100); }
 
if (sensorValue2 <470) {
  Serial.println("Left");
  Serial.print('L');
  delay(100); }
}

und der Empfänger

#define BRAKEVCC 0
#define CW   1
#define CCW  2
#define BRAKEGND 3
#define CS_THRESHOLD 100

int inApin[2] = {7, 4};  // INA: Clockwise input
int inBpin[2] = {8, 9}; // INB: Counter-clockwise input
int pwmpin[2] = {5, 6}; // PWM input
int cspin[2] = {2, 3}; // CS: Current sense ANALOG input
int enpin[2] = {0, 1}; // EN: Status of switches output (Analog pin)
int statpin = 13;
int speed = 100;

void setup()
{
 Serial.begin(115200);
 pinMode(statpin, OUTPUT);

 // Initialize digital pins as outputs
 for (int i=0; i<2; i++)
 {
   pinMode(inApin[i], OUTPUT);
   pinMode(inBpin[i], OUTPUT);
   pinMode(pwmpin[i], OUTPUT);
 }

 // Initialize braked
 for (int i=0; i<2; i++)
 {
   digitalWrite(inApin[i], LOW);
   digitalWrite(inBpin[i], LOW);
 }
}

/*----------------------------
 pmw value has to be < 1023.
 CCW=CounterClockwise
 CW=ClockWise
-----------------------------*/
void loop()
{   
  if (Serial.available() > 0) {
    if (Serial.read() == 'F'){
     motorGo(0, CCW, speed);      //Motor1
     motorGo(1, CW,  speed);      //Motor2                       
 }
   if (Serial.read() == 'B'){
     motorGo(0, CW, speed);      //Motor1
     motorGo(1, CCW, speed);      //Motor2     
 }
   if (Serial.read() == 'L'){
     motorGo(0, CW, 100);      //Motor1
     motorGo(1, CW, 100);      //Motor2     
}
if (Serial.read() == 'R'){
     motorGo(0, CCW, 100);      //Motor1
     motorGo(1, CCW, 100);      //Motor2
}
}
 


 if ((analogRead(cspin[0]) < CS_THRESHOLD) && (analogRead(cspin[1]) < CS_THRESHOLD))
   digitalWrite(statpin, HIGH);
}

void motorOff(int motor)
{
 // Initialize braked
 for (int i=0; i<2; i++)
 {
   digitalWrite(inApin[i], LOW);
   digitalWrite(inBpin[i], LOW);
 }
 analogWrite(pwmpin[motor], 0);
}

void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm)
{
 if (motor <= 1)
 {
   if (direct <=4)
   {
     // Set inA[motor]
     if (direct <=1)
       digitalWrite(inApin[motor], HIGH);
     else
       digitalWrite(inApin[motor], LOW);

     // Set inB[motor]
     if ((direct==0)||(direct==2))
       digitalWrite(inBpin[motor], HIGH);
     else
       digitalWrite(inBpin[motor], LOW);
     analogWrite(pwmpin[motor], pwm);
   }
 }
}

Motoren laufen und lassen sich ca. 2x ändern. Irgendwas muss ich noch ändern bezüglich fine tuning, sonst rattern die Ketten die ganze Zeit. Delay erhöhen von 100 auf 300? Danach einbauen, dass wenn keine Angabe die Motoren auf 0 gehen.

Hat jemand schon sowas in der Art programmiert?

Vielen Dank und Viele Grüße

Andreas

Deine serielle Auslese-Routine ist Unfug. Mit Serial.read() liest du ein Zeichen aus dem Eingangspuffer aus. Das musst du dann aber erst mal abspeichern. Und danach auf den abgespeicherten Wert abfragen. Nicht ständig read() machen. Wenn z.B. 'B' sendest, liest du das aus, dann vergleichst du auf 'F'. Danach liest du wieder ein Zeichen ein. Da kommt dann aber -1, da nur ein Zeichen geschickt wurde.

char command = Serial.read();

if (command == 'A')
{
}
else if (command == 'B')
{
}

Oder switch/case statt if/else

Senden passt aber wohl auch nicht so:

  Serial.println("Back");
  Serial.print('B');

Und ähnliches. "Back" soll wohl eine Debug Ausgabe sein. Das wird so aber auch an den anderen Arduino gesendet.

Serial ist die USB Schnittstelle und Pin 0/1. Da kannst du EIN Gerät dran anschließen. Entweder einen PC oder irgendein Schnittstellen Modul. Du darfst aber nicht "Back" an den Robotor senden wenn du dort nur auf 'B' wartest. Das kommt dann zwei mal an.

Ah vielen Dank. Hilft mir weiter!

Will die Geschichte sowieso noch was abändern.

  1. Thumbstick Für die linke Kette vorwärts = A Für die linke Kette rückwärts = C
  2. Thumbstick Für die rechte Kette vorwärts = B Für die rechte Kette rückwärts = D

Geschwindigkeit (speed) will ich dann mit den Knöpfen am LCD einstellen, aber soweit ist es noch nicht daher speed=100.

Serial ist bei mir das entsprechende Xbee Modul. Sobald das dran ist, übernimmt es RX/TX bzw. die Pin 0/1. Daher ist das soweit okay und funktioniert auch. Mega hat glaube ich 3 Serialports Uno 1.

Vielen Dank Andreas

Du kannst auch AltSoftSerial verwenden um eine serielle Schnittstelle in Software zu emulieren. Die geht zwar nicht mit so hohen Baudraten aber 9600 reicht hier locker.

https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html

Hallo liebe Mitbastler,

habe mein Sketch modifiziert. Jedoch ist mir aufgefallen, dass ich ja auch noch bremsen muss. Daher habe ich nochmal dran gesessen und den Code ergänzt. Leider scheint er nicht wirklich zu funktionieren.
Mein Wunsch wäre, ich drücke den linken Pad nach vorne - linke Kette fährt vorwärts, tu ich den Hebel nach hinten, fährt sie rückwärts. Lass ich den Hebel los bremst der Roboter. Die “Deadzone” des Thumbsticks liegt ca. bei 550. Daher habe ich die Bremse links (E) in diesen Bereich gesetzt. Wenn also Deadzone ist, dann sende E zum Empfänger und dieser setzt dann Speed auf 0. Leider klappt es nicht. Habt Ihr eine Idee, wie man das sauber lösen kann?

Sender Sketch:

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:

  int sensorValue1 = analogRead(A3);
  int sensorValue2 = analogRead(A4);
  int sensorValue3 = analogRead(A1);
  int sensorValue4 = analogRead(A2);

if (sensorValue1 >570){
  Serial.println("backward Left Track");
  Serial.print('A');
  delay(100); }

if (sensorValue3 >570){
  Serial.println("backward Right Track");
  Serial.print('B');
  delay(100); }


if (sensorValue1 <470) {
  Serial.println("Forward Left Track");
  Serial.print('C');
  delay(100); }

if (sensorValue3 <470) {
  Serial.println("Forward Right Track");
  Serial.print('D');
  delay(100); }

if (500 < sensorValue1 >560) {
  Serial.println ("Left Track brake");
  Serial.print ('E');
  delay (100); 
}

if (500 < sensorValue3 >560) {
  Serial.println ("Right Track brake");
  Serial.print ('F');
  delay (100); 
}

}

Empfänger Sketch

#define BRAKEVCC 0
#define CW   1
#define CCW  2
#define BRAKEGND 3
#define CS_THRESHOLD 100

int inApin[2] = {7, 4};  // INA: Clockwise input
int inBpin[2] = {8, 9}; // INB: Counter-clockwise input
int pwmpin[2] = {5, 6}; // PWM input
int cspin[2] = {2, 3}; // CS: Current sense ANALOG input
int enpin[2] = {0, 1}; // EN: Status of switches output (Analog pin)
int statpin = 13;
int speed = 100;

void setup()
{
 Serial.begin(115200);
 pinMode(statpin, OUTPUT);

 // Initialize digital pins as outputs
 for (int i=0; i<2; i++)
 {
   pinMode(inApin[i], OUTPUT);
   pinMode(inBpin[i], OUTPUT);
   pinMode(pwmpin[i], OUTPUT);
 }

 // Initialize braked
 for (int i=0; i<2; i++)
 {
   digitalWrite(inApin[i], LOW);
   digitalWrite(inBpin[i], LOW);
 }
}

/*----------------------------
 pmw value has to be < 1023.
 CCW=CounterClockwise
 CW=ClockWise
-----------------------------*/
void loop()
{   
  if (Serial.available() > 0) {
   char command = Serial.read();
   
   if (command == 'A'){
     motorGo(0, CCW, speed);      //Motor1                 
 }
   else if (command == 'B'){
     motorGo(1, CCW, speed);      //Motor2     
 }
   else if (command == 'C'){
     motorGo(0, CW, speed);      //Motor1
}
   else if (command == 'D'){
     motorGo(1, CCW, speed);      //Motor2
}
  else if (command == 'E'){
     motorGo(0, CW, 0);      //Motor1
}
else if (command == 'F'){
     motorGo(1, CCW, 0);      //Motor2
  
}
 }


 if ((analogRead(cspin[0]) < CS_THRESHOLD) && (analogRead(cspin[1]) < CS_THRESHOLD))
   digitalWrite(statpin, HIGH);
}

void motorOff(int motor)
{
 // Initialize braked
 for (int i=0; i<2; i++)
 {
   digitalWrite(inApin[i], LOW);
   digitalWrite(inBpin[i], LOW);
 }
 analogWrite(pwmpin[motor], 0);
}

void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm)
{
 if (motor <= 1)
 {
   if (direct <=4)
   {
     // Set inA[motor]
     if (direct <=1)
       digitalWrite(inApin[motor], HIGH);
     else
       digitalWrite(inApin[motor], LOW);

     // Set inB[motor]
     if ((direct==0)||(direct==2))
       digitalWrite(inBpin[motor], HIGH);
     else
       digitalWrite(inBpin[motor], LOW);
     analogWrite(pwmpin[motor], pwm);
   }
 }
}