Fehler beim Kompilieren "was not declared in this scope"?

Ich habe eine Funktion motor(); aus einem Programmteil erstellt der immer wieder zum Einsatz kommt. Das vereinfacht den Code ein wenig und macht es übersichtlicher.
Nun bekomme ich aber immer den Fehler: 'motor' was not declared in this scope. Warum? Klammern sind alle da was ich sehe und sonst sollte es doch auch gehen? Wo liegt der Hund begraben?

/*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 Pin configuration:

      Roboclaw 2x7A   =>  TX Pin D7       //Motor controller for dome drive (Roboclaw Pin S1) => RX
      Roboclaw 2x60A  =>  RX Pin D6       //Motor controller for feet drives (Roboclaw Pin S2, left/right) => TX
                          TX Pin D5       //Motor controller for feet drives (Roboclaw Pin S1, forward/reverse) => RX

      Arduino MEGA, SCL #0x3A      =>   Pin D19    //SCL, master device
      Arduino MEGA, SDA #0x3A      =>   Pin D18    //SDA, master device
      Arduino UNO, MP3 Shield TX   =>   Pin D10    //RX
      Arduino UNO, MP3 Shield RX   =>   Pin D11    //TX


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

 /**SETTINGS**/
const unsigned long Baudrate = 38400;  //starts serial port with a baudrate by 38400 b/s

const byte SpeedDD = 80;         //set the speed for dome drive (127=full speed, 0-127 slower to faster)
const byte SpeedFDLR = 100;      //set the maximum, normal speed for foot drive left/right (0=stop, 127=full speed, 0-127 slower to faster)
const byte SpeedFDUD = 100;      //set the maximum, normal speed for foot drive forward/backward (0=stop, 127=full speed, 0-127 slower to faster)

const byte SpeedFDLRfast = 120;  //set the maximum, fast speed for foot drive left/right (if joystick is pressed down) (0=stop, 127=full speed, 0-127 slower to faster)
const byte SpeedFDUDfast = 120;  //set the maximum, fast speed for foot drive forward/backward (if joystick is pressed down) (0=stop, 127=full speed, 0-127 slower to faster)

#define address 0x80             //address for Roboclaw from feet motors, address 128
#define addressDD 0x82           //address for Roboclaw from dome motor, address 130


/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

 //Definition of pinnumbers
#define RoboclawDomeTXpin 7  //Software serial Roboclaw dome drive TX defined on pin D7
#define RoboclawRXpin 6      //Software serial Roboclaw foot drive RX defined on pin D6
#define RoboclawTXpin 5      //Software serial Roboclaw foot drive TX defined on pin D5
#define RXpin 10             //Software serial RX defined on pin D10
#define TXpin 11             //Software serial TX defined on pin D11

 //Definition of designations for reading signals (signals to be received)
byte DD = 0;     //Dome drive
byte FDLR = 0;   //Foot drive left/right
byte FDUD = 0;   //Foot drive forward/backward
byte joybut = 0; //Foot drive joystick-button

byte BUT1 = 0;   //Button 1
byte BUT2 = 0;   //Button 2
byte BUT3 = 0;   //Button 3
byte BUT4 = 0;   //Button 4
byte BUT5 = 0;   //Button 5
byte BUT6 = 0;   //Button 6
byte BUT7 = 0;   //Button 7
byte BUT8 = 0;   //Button 8
byte BUT9 = 0;   //Button 9
byte BUT10 = 0;  //Button 10
byte BUT11 = 0;  //Button 11
byte BUT12 = 0;  //Button 12
byte BUT13 = 0;  //Button 13
byte BUT14 = 0;  //Button 14
byte BUT15 = 0;  //Button 15
byte BUT16 = 0;  //Button 16
byte BUT17 = 0;  //Button 17
byte BUT18 = 0;  //Button 18
byte BUT19 = 0;  //Button 19
byte BUT20 = 0;  //Button 20
byte BUT21 = 0;  //Button 21
byte BUT22 = 0;  //Button 22
byte BUT23 = 0;  //Button 23

byte autobut = 0;  //Automatic button

 //Definition of designations for storing signals (cache)
byte data[5];                   //create array for packet serial (feet and dome motors)
uint16_t crc = 0;               //checksum crc
byte retry = 2;                 //number of retried transmissions if failed
volatile byte dataReceived[2];  //byte array for received data over I2C
bool newData;                   //check for new data received

byte lastDD = 0;     //last status from dome drive
byte lastFDLR = 0;   //last status from foot drive, left/right
byte lastFDUD = 0;   //last status from foot drive, forward/backward
byte mapFDLR = 0;    //converted value FDLR (foot drive left/right) for the dc motor
byte mapFDUD = 0;    //converted value FDUD (foot drive forward/backward)( for the dc motor
byte mapDD = 0;      //converted value DD (dome drive left/right) for the dc motor

#include <Wire.h>             //adds library for I2C
#include <SoftwareSerial.h>   //adds library to define software serial ports

SoftwareSerial serial1(RXpin, TXpin);                    //create software serial "serial1" with RX, TX pins
SoftwareSerial Roboclaw(RoboclawRXpin, RoboclawTXpin);   //create software serial "Roboclaw" with RX, TX pins
SoftwareSerial RoboclawDome(8, RoboclawDomeTXpin);       //create software serial "RoboclawDome" with RX, TX pins


void setup() {
  Wire.begin(0x3A);             //starts I2C bus as slave on address 0x3A
  Wire.onReceive(readCommand);  //function to trigger when something is received over I2C

  //definition of input/output pins
  pinMode(RXpin, INPUT);    //pin RXpin is an input
  pinMode(TXpin, OUTPUT);   //pin TXpin is an output
  pinMode(RoboclawRXpin, INPUT);      //pin RoboclawRXpin is an input
  pinMode(RoboclawTXpin, OUTPUT);     //pin RoboclawTXpin is an output
  pinMode(RoboclawDomeTXpin, OUTPUT); //pin RoboclawDomeTXpin is an output
  
  serial1.begin(Baudrate);  //starts serial1 port with a baudrate by "Baudrate" (b/s)
  Roboclaw.begin(Baudrate);  //starts roboclaw port with a baudrate by "Baudrate" (b/s)
  RoboclawDome.begin(Baudrate);  //starts roboclawDome port with a baudrate by "Baudrate" (b/s)


  //initialization of the dome motor on startup
  motor(0,0, addressDD, RoboclawDome);  //command for forward, stop movement, address, serial port
  
  //initialization of the feet motors on startup
  motor(10,0, address, Roboclaw);       //command for turn right in mix mode, stop movement, address, serial port
  motor(8,0, address, Roboclaw);        //command for forward in mix mode, stop movement, address, serial port
  
}

void loop() {

  if(newData == true){                                    //if new data received is true, then make...

//Dome drive
  if(DD != lastDD){                                       //if DD (dome drive) not equal to lastDD, then make...
    if(0 <= DD && DD < 87){                               //if DD is between 0 and 90, then make...
      mapDD = map(DD, 90, 0, 0, SpeedDD);                 //read value from DD, convert the input value from 0 to 90 in a dc motor value from 0 to SpeedDD and store it to mapDD
      motor(0,mapDD, addressDD, RoboclawDome);            //command for forward, movement mapDD, address, serial port
    }
    else if(180 >= DD && DD > 93){                        //if DD is between 90 and 180, then make...
      mapDD = map(DD, 90, 180, 0, SpeedDD);               //read value from DD, convert the input value from 90 to 180 in a dc motor value from 0 to SpeedDD and store it to mapDD
      motor(1,mapDD, addressDD, RoboclawDome);            //command for backward, movement mapDD, address, serial port
    }
    else if(87 <= DD && DD <= 93){                        //if DD is 90, then make...
      motor(0,0, addressDD, RoboclawDome);                //command for forward, stop movement, address, serial port
    }
    lastDD = DD;                                          //stores DD on lastDD
  }


//Foot drive
  if(FDLR != lastFDLR && joybut == HIGH){                 //if FDLR (foot drive left/right) not equal to lastFDLR and joybut is equal to HIGH (not pressed), then make...
    if(0 <= FDLR && FDLR < 87){                           //if FDLR is between 0 and 90, then make...
      mapFDLR = map(FDLR, 90, 0, 0, SpeedFDLR);           //read value from FDLR, convert the input value from 0 to 90 in a dc motor value from 0 to SpeedFDLR and store it to mapFDLR
      motor(10,mapFDLR, address, Roboclaw);               //command for turn right in mix mode, movement mapFDLR, address, serial port
        while(Roboclaw.available() > 0) {
          if(Roboclaw.read() != 0xFF){
          for(retry=2; retry > 0 && Roboclaw.read() != 0xFF; retry--) {
            //Serial.print("retry = ");
            //Serial.println(map(retry,2,0,0,2));
            delay(10);
            Roboclaw.write(data, sizeof(data));
          }
          retry = 2;
          }
        }
    }
    else if(180 >= FDLR && FDLR > 93){                    //if FDLR is between 90 and 180, then make...
      mapFDLR = map(FDLR, 90, 180, 0, SpeedFDLR);         //read value from FDLR, convert the input value from 90 to 180 in a dc motor value from 0 to SpeedFDLR and store it to mapFDLR
      motor(11,mapFDLR, address, Roboclaw);               //command for turn left in mix mode, movement mapFDLR, address, serial port
    }
    else if(87 <= FDLR && FDLR <= 93){                    //if FDLR is 90, then make...
      motor(10,0, address, Roboclaw);                     //command for turn right in mix mode, stop movement, address, serial port
    }
    lastFDLR = FDLR;                                      //stores FDLR on lastFDLR
  }

  if(FDLR != lastFDLR && joybut == LOW){                  //if FDLR (foot drive left/right) not equal to lastFDLR and joybut is equal to LOW (pressed), then make...
    if(0 <= FDLR && FDLR < 87){                           //if FDLR is between 0 and 90, then make...
      mapFDLR = map(FDLR, 90, 0, 0, SpeedFDLRfast);       //read value from FDLR, convert the input value from 0 to 90 in a dc motor value from 0 to SpeedFDLRfast and store it to mapFDLR
      motor(10,mapFDLR, address, Roboclaw);               //command for turn right in mix mode, movement mapFDLR, address, serial port
    }
    else if(180 >= FDLR && FDLR > 93){                    //if FDLR is between 90 and 180, then make...
      mapFDLR = map(FDLR, 90, 180, 0, SpeedFDLRfast);     //read value from FDLR, convert the input value from 90 to 180 in a dc motor value from 0 to SpeedFDLRfast and store it to mapFDLR
      motor(11,mapFDLR, address, Roboclaw);               //command for turn left in mix mode, movement mapFDLR, address, serial port
    }
    else if(87 <= FDLR && FDLR <= 93){                    //if FDLR is 90, then make...
      motor(10,0, address, Roboclaw);                     //command for turn right in mix mode, stop movement, address, serial port
    }
    lastFDLR = FDLR;                                      //stores FDLR on lastFDLR
  }

  if(FDUD != lastFDUD && joybut == HIGH){                 //if FDUD (foot drive forward/backward) not equal to lastFDUD and joybut is equal to HIGH (not pressed), then make...
    if(0 <= FDUD && FDUD < 87){                           //if FDUD is between 0 and 90, then make...
      mapFDUD = map(FDUD, 90, 0, 0, SpeedFDUD);           //read value from FDUD, convert the input value from 0 to 90 in a dc motor value from 0 to SpeedFDUD and store it to mapFDUD
      motor(8,mapFDUD, address, Roboclaw);                //command for forward in mix mode, movement mapFDUD, address, serial port
    }
    else if(180 >= FDUD && FDUD > 93){                    //if FDUD is between 90 and 180, then make...
      mapFDUD = map(FDUD, 90, 180, 0, SpeedFDUD);         //read value from FDUD, convert the input value from 90 to 180 in a dc motor value from 0 to SpeedFDUD and store it to mapFDUD
      motor(9,mapFDUD, address, Roboclaw);                //command for backward in mix mode, movement mapFDUD, address, serial port
    }
    else if(87 <= FDUD && FDUD <= 93){                    //if FDUD is 90, then make...
      motor(8,0, address, Roboclaw);                      //command for forward in mix mode, stop movement, address, serial port
    }
    lastFDUD = FDUD;                                      //stores FDUD on lastFDUD
  }

  if(FDUD != lastFDUD && joybut == LOW){                  //if FDUD (foot drive forward/backward) not equal to lastFDUD and joybut is equal to LOW (pressed), then make...
    if(0 <= FDUD && FDUD < 87){                           //if FDUD is between 0 and 90, then make...
      mapFDUD = map(FDUD, 90, 0, 0, SpeedFDUDfast);       //read value from FDUD, convert the input value from 0 to 90 in a dc motor value from 0 to SpeedFDUDfast and store it to mapFDUD
      motor(8,mapFDUD, address, Roboclaw);                //command for forward in mix mode, movement mapFDUD, address, serial port
    }
    else if(180 >= FDUD && FDUD > 93){                    //if FDUD is between 90 and 180, then make...
      mapFDUD = map(FDUD, 90, 180, 0, SpeedFDUDfast);     //read value from FDUD, convert the input value from 90 to 180 in a dc motor value from 0 to SpeedFDUDfast and store it to mapFDUD
      motor(9,mapFDUD, address, Roboclaw);                //command for backward in mix mode, movement mapFDUD, address, serial port
    }
    else if(87 <= FDUD && FDUD <= 93){                    //if FDUD is 90, then make...
      motor(8,0, address, Roboclaw);                      //command for forward in mix mode, stop movement, address, serial port
    }
    lastFDUD = FDUD;                                      //stores FDUD on lastFDUD
  }

  newData = false;                          //set new data received to false for receiving new data
  }
}


//Function for reading a command and store it to designation
void readCommand(int bytes){                //function readCommand takes the length of received data (bytes) from onReceive and make...

  if(bytes == 2){                           //if bytes is equal to 2 (received bytes), then make...
    dataReceived[0] = Wire.read();          //store the first byte from received data over I2C to dataReceived array
    dataReceived[1] = Wire.read();          //store the second byte from received data over I2C to dataReceived array

    switch(dataReceived[0]){
      case 'X' : DD = dataReceived[1];      //if the first byte in the array dataReceived is equal to X, then store the second byte from the array dataReceived to DD
                 break;                     //finish the command and return
      case 'Y' : FDLR = dataReceived[1];
                 break;
      case 'Z' : FDUD = dataReceived[1];
                 break;
      case 'd' : joybut = dataReceived[1];
                 break;
      case 'e' : BUT1 = dataReceived[1];
                 command('e',BUT1, serial1);  //send command e and the value from BUT1 over serial to the next Arduino
                 break;
      case 'f' : BUT2 = dataReceived[1];
                 command('f',BUT2, serial1);
                 break;
      case 'g' : BUT3 = dataReceived[1];
                 command('g',BUT3, serial1);
                 break;
      case 'i' : BUT5 = dataReceived[1];
                 command('i',BUT5, serial1);
                 break;
      case 'j' : BUT6 = dataReceived[1];
                 command('j',BUT6, serial1);
                 break;
      case 'k' : BUT7 = dataReceived[1];
                 command('k',BUT7, serial1);
                 break;
      case 'm' : BUT9 = dataReceived[1];
                 command('m',BUT9, serial1);
                 break;
      case 'n' : BUT10 = dataReceived[1];
                 command('n',BUT10, serial1);
                 break;
      case 'o' : BUT11 = dataReceived[1];
                 command('o',BUT11, serial1);
                 break;
      case 'q' : BUT13 = dataReceived[1];
                 command('q',BUT13, serial1);
                 break;
      case 'r' : BUT14 = dataReceived[1];
                 command('r',BUT14, serial1);
                 break;
      case 's' : BUT15 = dataReceived[1];
                 command('s',BUT15, serial1);
                 break;
      case 't' : BUT16 = dataReceived[1];
                 command('t',BUT16, serial1);
                 break;
      case 'u' : BUT17 = dataReceived[1];
                 command('u',BUT17, serial1);
                 break;
      case 'v' : BUT18 = dataReceived[1];
                 command('v',BUT18, serial1);
                 break;
    }
    newData = true;
  }
}


//Function for sending a command over serial
void command(const char command, const byte value, Stream& stream){
  stream.print(command);
  stream.println(value);
}


//Function for driving the feet and dome motors over serial
void motor(const byte command, const byte value, const byte address, Stream& stream){
  data[0] = address;                            //write address in data array
  data[1] = command;                            //write command for forward/reverse/left/right in data array
  data[2] = value;                              //write movement speed in data array
  for(byte index = 0; index < 3; index++){      //create the checksum for the array data[i] with 0 <= i <= 3
    crc16(data[index]);                         //call the function crc16
  }
  //crc = getCRC();
  data[3] = crc >> 8;                           //store checksum in data array
  data[4] = crc;
  stream.write(data, sizeof(data));             //send the data array by serial
  crc = 0;                                      //clear the checksum
}


//Calculates CRC16 of nBytes of data[index] in byte array
void crc16(uint8_t data) {

  int i;
  crc = crc ^ ((uint16_t)data << 8);
  for (i=0; i<8; i++){
    if (crc & 0x8000){
      crc = (crc << 1) ^ 0x1021;
    }
    else{
      crc <<= 1;
    }
  }
}

uint16_t getCRC() {
  return crc;
}

Du definierst motor() erst hinter den Verwendungen. Deswegen weiß der Compiler da noch nicht, wie die Funktionssignatur aussieht.

Drei Lösungswege:

  • Du verschiebst den Code von motor() im Sketch vor setup()
  • Du schreibst zu Deinen ganzen Definitionen und Deklarationen noch eine für die Vorwärtsdeklaration von motor() (void motor(const byte command, const byte value, const byte address, Stream& stream);)
  • Du schiebst die Funktion in ein separates File motor.h und holst sie dir mit #include "motor.h" in Deinen Sketch.

Also vereinfacht ausgedrückt ist es, weil ich schon im setup diese Funktion benutze? Weil die andern Funktionen gehen alle ohne Probleme, sind aber auch erst in der Loop benutzt.

Was genau meinst Du mit Punkt zwei "Vorwärtsdeklaration"?

Normalerweise müßte das die IDE automatisch machen aber manchmal gehts nicht. Da hilft nur eine manuele Deklaration.

Grüße Uwe

In dem Fall wird einfach:

void motor(const byte command, const byte value, const byte address, Stream& stream);

noch vor dem Setup eingefügt, richtig?

Kreuzantwort...

Steht doch schon da?

void motor(const byte command, const byte value, const byte address, Stream& stream);

Irgendwo am Anfang Deines Sketches einfügen...

Kein Problem! Vielen Dank :slight_smile:

Könnte das nicht mittels array [ ] gemacht werden?
Oder noch besser mit einer einzigen Variable die in allen case verwendet wird?
Grüße Uwe

Musst Du nicht noch eine passende lib dazu mitnehmen...?

Ich habe es mal so definiert. Mittels Array?
Es wird für jeden Taster bei Empfang den Wert entsprechend gespeichert. Mit nur einen Variablen wird dies schwierig?!

Nö, sogar noch einfacher. :wink:

Nö, weil ich mit der Funktion motor(); die Befehle sende und somit einiges an Speicherplatz spare :wink:

Macht die IDE auch, aber das Problem liegt tiefer und zeigt mal wieder wie gefährlich ein #define anstelle von const byte .. sein kann.

Das Problem liegt in dieser Zeile:

#define address 0x80             //address for Roboclaw from feet motors, address 128

Der Name address wurde aber auch als paramtername im motor() benutzt. Der Precompiler hat das stur durch 0x80 ersetzt, was natürlich als Parametername fatal ist.

Wenn man das stattdessen als

const byte address = 0x80;             //address for Roboclaw from feet motors, address 128

definiert, funktioniert es, denn im Gegensatz zum Preprozessor ist der Compiler schlau genug, den Unterschied zu erkennen, und den gleichnamigen Parameter von motor() getrennt zu behandeln.

Ein Problem habe ich jetzt aber noch! Wenn ich nun vor dem Setup die Funktion motor() definiere, dann erhalte ich folgenden Fehler: expected ',' or ';' before 'const'
Dies für die Deklaration der Adressen 0x80 und 0x82 oben bei den Settings. Vorher ging alles und nun gibts nur Probleme mit dem Erstellen der Funktion.... fragt sich dann was wirlich einfacher gewesen wäre :smiley:

Ach, ich hab das versucht, ging auch nicht!
..... vielleicht habe ich aber noch die Deklaration von motor() vor dem Setup vergessen zu löschen!

Edit:
Ich glaube es ist Zeit für Feierabend! Habe das Semikolon vergessen! Vielen Dank an alle, jetzt funzts :smiley:

Hast Du mit ein Beispiel dazu oder kannst es zeigen?

Super, hätte mich auch sonst gewundert, denn ob Du die Funktionsdeklaration vor das setup schreibst, oder nicht darf keinen Unterschied machen ( ist ja nichts anderes als das, was die IDE auch macht ).

Ja, man merkt dann mal wieder wenn es Zeit wird alles bei Seite zu legen und was anderes zu machen! Bin schon wieder viel zu lange dran.

Hallo,
die Abfragen kannst Du noch ändern

DD ist als byte deklariert es kann nicht kleiner 0 werden
if( DD < 87)

dann ist auch noch die Warnung weg
Heinz

Das sagt ja die Fehlermeldung.

Ja, aufhören wenn die Fehler sich häufen und später mit frischem Gehirn weitermachen ist eine gute Idee.

Abgesehen von der besseren Lösung mittels einer constant-Variable würde auch ein anderer, unbenutzter Name das Problem lösen? Wobei die Gefahr einer Doppelverwendung einer Zeichenfolge ja immer bleibt.

Grüße Uwe