Motorshield + IRDiode, Arduino läuft immer in void setup

Hallo,

ich versuche einen Arduino zum IR-Empfänger um zu bauen. Weihnachten steht vor der Tür und für meinen Sohn möchte ich einen Ferngesteuerten SIKU-Mähdrescher bauen.

Als Fernbedienung möchte ich die vorhanden SIKU-Control-IR-Fernbedinung benutzten welche auf 455 khz IR-Singale sendet.

Grundlage für die IR-Verarbeitung war dieser Sketch: // Siku Control IR Receiver// Version 5// by SamuSC (modelleicher)// Date - Pastebin.com.

Als Arduino nehme ich den UNO R3 und dazu habe ich mehere L293D Motor Drive Shield’s (auch die Version V2) getestet.
Laut Doku und dem Platinenlayout sollen PIN 2 und PIN 13 nicht belegt sein.
Als IR-Diode nutze ich eine TSOP7000.

Ich hoffe, dass ich nun alle Merkmale aufgeschrieben habe.

Die Projekte getrennt von einander funktionieren.
Auch das Projekt"Motorsteuerung" in Verbindung mit einer “KY-022”-IR-Diode fuktioniert.
Ich kann IR-Befehle auslesen und ausgeben und ich kann die Motoren steuern bzw. auch die IR-Befehle verarbeiten und den Motor steuern.
Sobald ich jedoch die Library #include <AFMotor.h> aktiviere oder wenn ich den Motor wie in diesem Beispiel anspreche, springt der Arduino immer aus dem Befehl loop und gibt wieder “Starting up…” aus.
Ich habe es mit PIN 2 und PIN 13 versucht. Ich habe es mit unterschiedlichen Motorkanälen versucht. Ich habe diverse Stromquellen versucht. Ohne Erfolg.
Ich habe weiter Serial.println eingebaut und Serial.println(“irInPin”); wird noch ausgegeben, mehr nicht.

// Siku Control IR Receiver
// Version 5
// by SamuSC (modelleicher)
// Date 01/06/2014
// last edit: 01/07/2014
byte times[56]; // we have 57 times because 57 bits
byte bits[56];  // and because of that we (hopefully, if it receives all correct) have 57 Bits 

//received raw bytes
byte raw_bytes[7];

// last checksum
byte lastChecksum;

// received positions and states stored in those variables
byte ch1pos, ch2pos, ch3pos, ch4pos, ch5pos; 
boolean sw1state, sw2state, sw3state, sw4state;
byte ch1direction;
boolean blLiState = false, blReState = false;
//von mir
int lastSpeed;

int oldMillis = 0;

byte irInPin = 2;

// Timing for high and low Bits
byte hbma = 62;  // high bit time max in µS
byte hbmi = 52;  // high bit time min in µS
byte lbma = 42;  // low bit time max in µS
byte lbmi = 32;  // low bit time min in µS

byte adress = 3; // Adress from 1 to 4

// and finally, we load the servos.. (YEAH!)
#include <Servo.h>
#include <AFMotor.h>

//Servo servo1;               // DC hobby servo
//AF_DCMotor motor4(4);

void setup()
{
  pinMode(irInPin, INPUT);
  //servo1.attach(9);         // turn on servo
  //servo1.write(100);
  //motor4.setSpeed(0);
  //motor4.run(RELEASE); 
  // for debugging
  Serial.begin(9200); 
  Serial.println("Starting up...");
}

// checksum was figured out by the rc tractor guy here:
// https://www.youtube.com/watch?v=nLxTGGqyFkQ&t=36s
byte getChecksum()
{
  byte receivedChecksum;

  byte cs_ch1 = flipByte(raw_bytes[1]);
  byte cs_ch2 = flipByte(raw_bytes[2]);
  byte cs_ch3 = flipByte(raw_bytes[3]);
  byte cs_ch4 = flipByte(raw_bytes[4]);
  byte cs_ch5 = flipByte(raw_bytes[5]);
  byte cs_ch6 = flipByte(raw_bytes[6]);

  receivedChecksum = addBytes(cs_ch1, cs_ch2);
  receivedChecksum = addBytes(receivedChecksum, cs_ch3);
  receivedChecksum = addBytes(receivedChecksum, cs_ch4); 
  receivedChecksum = addBytes(receivedChecksum, cs_ch5);
  receivedChecksum = addBytes(receivedChecksum, cs_ch6);

  receivedChecksum = flipByte(receivedChecksum);
  
  return receivedChecksum;
}

// function to flip a byte (least significant to most significant and other way around)
byte flipByte(byte input)
{
  byte output;
  for (byte i = 0; i < 8; i++) 
  {
      bitWrite(output, i, bitRead(input, 7-i));
  }
  return output;
}

// function to add two bytes binary (i guess there is a better way but i don't know any)
byte addBytes(byte byte1, byte byte2)
{
  byte output;
  for (byte i = 0; i < 8; i++)
  {
      if (bitRead(byte1, i) == 0 && bitRead(byte2, i) == 1 || bitRead(byte1, i) == 1 && bitRead(byte2, i) == 0) {bitWrite(output, i, 1);}
      else if(bitRead(byte1, i) == 1 && bitRead(byte2, i) == 1) {bitWrite(output, i, 0);}
      else {bitWrite(output, i, 0);}
  }
  return output;
}

// this function returns if a bit is high or low by the received time
byte timeToBit(byte time)  
{
   byte returnBit; 
   if (time > lbmi && time < lbma) {returnBit = 0;}
   else if (time > hbmi && time < hbma) {returnBit = 1;}
   return returnBit;
}


void loop()
{
  
  // wait for bits to receive
  times[0] = pulseIn(irInPin, LOW);
  if (times[0] > 45 && times[0] < 50) // found startbit
  {
    for (byte i = 1; i <= 56; i++)  // receive other 56 bits 
    {
       times[i] = pulseIn(irInPin, LOW);
       Serial.println("irInPin");  
    }

    // check if the received adress maches our adress:
    // first 4 bits of the first byte make up the adress.
    // adress 1 is 1000, adress 2 is 0100, adress 3 is 0010 and adress 4 is 0001.
    if (timeToBit(times[1]) == 1 && adress == 1 || timeToBit(times[2])== 1 && adress == 2 || timeToBit(times[3]) == 1 && adress == 3 || timeToBit(times[4]) == 1 && adress == 4)
    { 
      // adress of the received bytes matched our adress.. thats good! 

      // now convert all times to bits since a high bit is a long time and low bit is a short time pulse  
      for (byte r = 1; r <= 56; r++)   
      {
         bits[r] = timeToBit(times[r]); 
                Serial.println("timeToBit");  
      }

      // and convert the bits to the matching raw bytes
      byte bitsCnt = 1;
      for (byte c = 1; c <= 7; c++)
      {
          for (byte x = 0; x <= 7; x++)
          {
              bitWrite(raw_bytes[c], x, bits[bitsCnt]);
              bitsCnt++;
          }
      }

      // check the checksum and only continue if working
      lastChecksum = getChecksum();

      if (lastChecksum = raw_bytes[7]) 
      {
        
          // now the channels..
          //
          // note that the bytes are sent left-right by the siku controller.
          // but they are actually the right way around when used, right to left.
          // so everything has to be reversed.
          // Byte 1:
          // The first four bits (left-right) of byte 1 are the adress, the other for bits make the for light switch states
          sw1state = bitRead(raw_bytes[1], 3);
          sw2state = bitRead(raw_bytes[1], 2);
          sw3state = bitRead(raw_bytes[1], 1);
          sw4state = bitRead(raw_bytes[1], 0);
          //
          // Byte 2:
          // Acceleration Channel. The first 7 (left-right) bits are used to calculate the speed.
          // The last bit is used for direction.
          for (byte i = 0; i <= 6; i++)
          {
              bitWrite(ch1pos, i, bitRead(raw_bytes[2], i));
          }
          ch1direction = bitRead(raw_bytes[2], 7);
          //
          // Byte 3:
          // Steering Channel. The whole byte is used for steering position.
          for (byte i = 0; i <= 7; i++)
          {
              bitWrite(ch2pos, i, bitRead(raw_bytes[3], i));
          }
          //
          // Byte 4:
          // Extra function. The fist 7 (left-right) bits are used for this channel.
          // The left turn signal is on the last bit.
          for (byte i = 0; i <= 6; i++)
          {
              bitWrite(ch3pos, i, bitRead(raw_bytes[4], i));
          }
          blLiState = bitRead(raw_bytes[4], 7);
          //
          // Byte 5:
          // Extra function 2. The first 7 (left-right) bits are used for this channel.
          // The right turn signal is on the last bit.
          for (byte i = 0; i <= 6; i++)
          {
              bitWrite(ch4pos, i, bitRead(raw_bytes[5], i));
          }
          blReState = bitRead(raw_bytes[5], 7);           
          //
          // Byte 6:
          // Extra function 3. This channel uses all 8 bits.
          for (byte i = 0; i <= 7; i++)
          {
              bitWrite(ch5pos, i, bitRead(raw_bytes[6], i));
          }
          // Byte 7: Checksum
          // The Checksum is calculated by byte-flipping Byte 1 to 6, adding them together and byte-flipping the result again.
       }
       
              
      String mySendString = "x";
     //mySendString = ("x", String(adress) , "x" , String(ch1pos) , "x" , String(ch2pos) , "x" , String(ch3pos) , "x" , String(ch4pos) , "x" , String(ch5pos) , "x0x0x0x0x" , String(blLiState) , "x" , String(blReState));
      mySendString = String(ch1pos);
      //if (int(ch1pos) < 50 ) {Serial.println("Vorwärts");}  //RunEngine(1000,255,1,100);} //Vorwärts
      Serial.println(mySendString);  
    }   
  }
  }

Der springt nicht aus dem Loop, sondern bootet neu. Das könnte ein ein Zeichen für ungenügende Stromversorgung sein. Die USB-Versorgung schaltet normalerweise bei 500 mA ab.

Gruß Tommy

Ich habe es jetzt mit einem 9 Volt Netzteil und einer LED welche im Setup ein und ausgeschaltet wird kontrolliert. Der Arduino durchläuft endlos die Setup-Routine und hört erst auf, wenn ich die Fernbedienung ausschalte.

Sendet denn deine IR-Fernbedienung ständig ?
Was ist das für eine Fernbedienung ?

Wenn es mit der Fernbedienung zusammenhängt, kann nicht das Setup alleine laufen, das ist in deinem Sketch nicht zu erkennen.

pack doch mal in deine loop() auch ein paar Serial.println() rein.

z.B.: gleich am Anfang ein Serial.println("loop 1");
und dann immer wieder vor Funktionsaufrufen Serial.print("loop 2");Serial.print("loop 3"); etc.

So kannst du rausfinden an welcher Stelle er rausfliegt.
Setup verläßt er definitiv.

Die Fernbedienung sendet permanent Datensätze um die Steuerbefehle immer wieder mit dem Empfänger ab zu gleichen. In meinem Sketch wird über das letzte “Serial.println” normalerweise, die Stellung des Gashebels ausgegeben. Bis dahin kommt er leider nicht. Auf der Fernbedienung ist Adresse 3 gewählt wie im Sketch vorgesehen.
SIKU-6701-Fernsteuermodul

Im “loop” sind “Serial.println’s” vorhanden. Der erste “Serial.println” wird noch ausgegeben. Ich habe jetzt noch einmal zur Sicherheit 2 “Serial.println’s” ans Ende des Loops und der If-Bedinung welche die Adresse ausgibt geschrieben. Sieht nun so aus, (siehe Bild im Anhang

Zwischenablage03.jpg

Wie kann man nur so deppert sein und einen Text als Bild einbinden?

Setze Deinen Sketch bitte direkt in den Beitrag, wenn Du willst, das den jemand liest. Benutze dazu Codetags (</> oben links im Editor oder lies diese Beschreibung.)

Gruß Tommy

Tommy56:
Wie kann man nur so deppert sein und einen Text als Bild einbinden?

Setze Deinen Sketch bitte direkt in den Beitrag, wenn Du willst, das den jemand liest. Benutze dazu Codetags (</> oben links im Editor oder lies diese Beschreibung.)

Gruß Tommy

Sorry Tommy56 aber jetzt wirds bisschen komisch. Im ersten Post ist der Sketch im CodeTags. Ich verzichte jetzt drauf mich hier selbst zu Zitieren. Den Screenshoot habe ich gemacht um zu verdeutlichen das Mehrmals die Setup-Routine durchlaufen wird.

Und damit ist klar, dass dein Sketch durchlaufen wird und er aus dem Sketch rausfliegt.
Also resettet.

Mehrmals das setup abarbeiten deutet auf einen Reset hin.
Ein Kandidat auf einen ungewollten Reset sind Arrays die außerhalb des Indexs angesprochen werden wie Du es zB in
for (byte i = 1; i <= 56; i++)
machst.

byte times[56];
bedeutet ein Array mit 56 Elementen und einem Index von 0 bis 55.

gleiches gilt für raw_bytes

Grüße Uwe

klaas123:
Sorry Tommy56 aber jetzt wirds bisschen komisch. Im ersten Post ist der Sketch im CodeTags. Ich verzichte jetzt drauf mich hier selbst zu Zitieren. Den Screenshoot habe ich gemacht um zu verdeutlichen das Mehrmals die Setup-Routine durchlaufen wird.

Auch die Ausgabe vom seriellen Monitor ist ein Text, den man als Text angeben sollte (z.B. auch in Codetags) und nicht als Bild anhängen.

Gruß Tommy

klaas123:
Ich habe jetzt noch einmal zur Sicherheit 2 "Serial.println's" ans Ende des Loops und der If-Bedinung welche die Adresse ausgibt geschrieben.

Und, hast du auch mal eines an den Anfang von Loop gesetzt, wie ich empfahl?
Dann kannst du erkennen, ob er in die Loop reinspringt.

An sonsten hat Uwe natürlich recht. Mit
byte times[56]; // we have 57 times because 57 bits
erzeugst du ein Array mit 56 Plätzen, nicht 57.
Also times[0] bis times[55]

guntherb:
An sonsten hat Uwe natürlich recht. Mit
byte times[56]; // we have 57 times because 57 bits
erzeugst du ein Array mit 56 Plätzen, nicht 57.
Also times[0] bis times[55]

Außerdem mit
for (byte i = 1; i <= 56; i++)
deckst Du den Index von 1 bis 56 ab und damit 55 Elemente des Arrays und nicht 56 oder 57.
Die Variable times[56] liegt außerhalb des für das Array reservierten Speicherplatz und überschreibt den Speicherplatz dahinter das in Deinem Fall zu einem Reset führt.

Grüße Uwe

Hallo und vielen Dank für die Hilfe. :slight_smile:
Nachdem ich die größen der Arrays auf 57 angepasst habe, funktioniert es.
Ich hoffe heute bekomme ich ohne weiter Probleme den Mähdrescher zum Laufen.
Dann kann Weihnachten kommen. :slight_smile: