Skocz do zawartości

Start Zumo za pomocą pilota podczerwieni.


Mokkori

Pomocna odpowiedź

Witam. Próbuję napisać kod który za pomocą odbiornika podczerwieni wbudowanego w zestaw Zumo32u4 wystartować robota. Mój pomysł jest taki by wykorzystać kod z przykładów ze sterowaniem go za pomocą pilota i zrobić tak by każdy możliwy sygnał traktował jako start.

Przy kompilacji kodu wyskakuje mi następujący błąd.

Kod

/* This example shows how to use the receivers for the infrared
proximity sensors on the Zumo 32U4 to detect and decode commands
from an infrared remote.  This code is designed to work with the
Mini IR Remote Control available from Pololu:

 https://www.pololu.com/product/2777

For this code to work, jumpers on the front sensor array should
be installed in order to connect pin 4 to RGT and connect pin 20
to LFT.

The arrow buttons control the robot's movement, while the number
buttons from 1 to 3 play different notes on the buzzer.

To change what actions are performed when a button press is
detected, you should change the processRemoteCommand and
stopCurrentCommand functions.

If you have a different remote that uses the NEC protocol with a
38 kHz, 940 nm infrared emitter, it should be possible to make it
work with this code.  You can use this code to decode the
messages from your remote, and then you can edit the constants in
RemoteConstants.h to match what was transmitted from your
remote. */

#include <Wire.h>
#include <Zumo32U4.h>
#include "RemoteConstants.h"
#include "RemoteDecoder.h"


Zumo32U4LCD lcd;
Zumo32U4ButtonA buttonA;
Zumo32U4Buzzer buzzer;
Zumo32U4Motors motors;
Zumo32U4LineSensors lineSensors;
Zumo32U4ProximitySensors proxSensors;
unsigned int lineSensorValues[3];

// When the reading on a line sensor goes below this value, we
// consider that line sensor to have detected the white border at
// the edge of the ring.  This value might need to be tuned for
// different lighting conditions, surfaces, etc.
const uint16_t lineSensorThreshold = 1000;

// The speed that the robot uses when backing up.
const uint16_t reverseSpeed = 400;

// The speed that the robot uses when turning.
const uint16_t turnSpeed = 400;

// The speed that the robot usually uses when moving forward.
// You don't want this to be too fast because then the robot
// might fail to stop when it detects the white border.
const uint16_t forwardSpeed = 400;

// These two variables specify the speeds to apply to the motors
// when veering left or veering right.  While the robot is
// driving forward, it uses its proximity sensors to scan for
// objects ahead of it and tries to veer towards them.
const uint16_t veerSpeedLow = 0;
const uint16_t veerSpeedHigh = 500;

// The speed that the robot drives when it detects an opponent in
// front of it, either with the proximity sensors or by noticing
// that it is caught in a stalemate (driving forward for several
// seconds without reaching a border).  400 is full speed.
const uint16_t rammingSpeed = 500;

// The amount of time to spend backing up after detecting a
// border, in milliseconds.
const uint16_t reverseTime = 450;

// The minimum amount of time to spend scanning for nearby
// opponents, in milliseconds.
const uint16_t scanTimeMin = 400;

// The maximum amount of time to spend scanning for nearby
// opponents, in milliseconds.
const uint16_t scanTimeMax = 2100;

// The amount of time to wait between detecting a button press
// and actually starting to move, in milliseconds.  Typical robot
// sumo rules require 5 seconds of waiting.
const uint16_t waitTime = 0;//5000;

// If the robot has been driving forward for this amount of time,
// in milliseconds, without reaching a border, the robot decides
// that it must be pushing on another robot and this is a
// stalemate, so it increases its motor speed.
const uint16_t stalemateTime = 4000;

// This enum lists the top-level states that the robot can be in.
enum State
{
 StatePausing,
 StateWaiting,
 StateScanning,
 StateDriving,
 StateBacking,
};

State state = StatePausing;

enum Direction
{
 DirectionLeft,
 DirectionRight,
};

// scanDir is the direction the robot should turn the next time
// it scans for an opponent.
Direction scanDir = DirectionLeft;

// The time, in milliseconds, that we entered the current top-level state.
uint16_t stateStartTime;

// The time, in milliseconds, that the LCD was last updated.
uint16_t displayTime;

// This gets set to true whenever we change to a new state.
// A state can read and write this variable this in order to
// perform actions just once at the beginning of the state.
bool justChangedState;

// This gets set whenever we clear the display.
bool displayCleared;


// This variable sets the amount of time (in milliseconds) that
// we wait before considering the current message from the remote
// to have expired.  This type of remote typically sends a repeat
// command every 109 ms, so a timeout value of 115 was chosen.
// You can increase this timeout to 230 if you want to be more
// tolerant of errors that occur while you are holding down the
// button, but it will make the robot slower to respond when you
// release the button.
const uint16_t messageTimeoutMs = 115;

// This variable is true if the last message received from the
// remote is still active, meaning that we are still performing
// the action specified by the message.  A message will be active
// if the remote button is being held down and the robot has been
// successfully receiving messages from the remote since the
// button was pressed.
bool messageActive = false;

// This is the time that the current message from the remote was
// last verified, in milliseconds.  It is used to implement the
// timeout defined above.
uint16_t lastMessageTimeMs = 0;



RemoteDecoder decoder;

void setup()
{

 decoder.init();
 Serial.begin(9600);
 lcd.clear();
 lcd.print(F("Waiting"));

 lineSensors.initThreeSensors();
 proxSensors.initThreeSensors();

 changeState(StatePausing);
}

//if (processRemoteMessage(const uint8_t * message)==true){


void loop()
{
 bool buttonPress = buttonA.getSingleDebouncedPress();
 bool rushb;

rushb = false; 
if (processRemoteMessage(const uint8_t * message)==true){
 rushb=true;
 }
 if (state == StatePausing)
 {
   // In this state, we just wait for the user to press button
   // A, while displaying the battery voltage every 100 ms.

   motors.setSpeeds(0, 0);

   if (justChangedState)
   {
     justChangedState = false;
     lcd.print(F("Press A"));
   }

   if (displayIsStale(100))
   {
     displayUpdated();
     lcd.gotoXY(0, 1);
     lcd.print(readBatteryMillivolts());
   }

   if (rushb==true)
   {
     // The user pressed button A, so go to the waiting state.
     changeState(StateWaiting);
   }
 }
 else if (rushb==true)
 {
   // The user pressed button A while the robot was running, so pause.
   changeState(StatePausing);
 }
 else if (state == StateWaiting)
 {
   // In this state, we wait for a while and then move on to the
   // scanning state.

   motors.setSpeeds(0, 0);

   uint16_t time = timeInThisState();

   if (time < waitTime)
   {
     // Display the remaining time we have to wait.
     uint16_t timeLeft = waitTime - time;
     lcd.gotoXY(0, 0);
     lcd.print(timeLeft / 1000 % 10);
     lcd.print('.');
     lcd.print(timeLeft / 100 % 10);
   }
   else
   {
     // We have waited long enough.  Start moving.
     changeState(StateScanning);

     /*if(rushb==true){
       changeState(StateScanning);
       }
       else{
          changeState(StatePausing);
         }*/

   }
 }
 else if (state == StateBacking)
 {
   // In this state, the robot drives in reverse.

   if (justChangedState)
   {
     justChangedState = false;
     lcd.print(F("back"));
   }

   motors.setSpeeds(-reverseSpeed, -reverseSpeed);

   // After backing up for a specific amount of time, start
   // scanning.
   if (timeInThisState() >= reverseTime)
   {
     changeState(StateScanning);
   }
 }
 else if (state == StateScanning)
 {
   // In this state the robot rotates in place and tries to find
   // its opponent.

   if (justChangedState)
   {
     justChangedState = false;
     lcd.print(F("scan"));
   }

   if (scanDir == DirectionRight)
   {
     motors.setSpeeds(turnSpeed, -turnSpeed);
   }
   else
   {
     motors.setSpeeds(-turnSpeed, turnSpeed);
   }

   uint16_t time = timeInThisState();

   if (time > scanTimeMax)
   {
     // We have not seen anything for a while, so start driving.
     changeState(StateDriving);
   }
   else if (time > scanTimeMin)
   {
     // Read the proximity sensors.  If we detect anything with
     // the front sensor, then start driving forwards.
     proxSensors.read();
     if (proxSensors.countsFrontWithLeftLeds() >= 2
       || proxSensors.countsFrontWithRightLeds() >= 2)
     {
       changeState(StateDriving);
     }
   }
 }
 else if (state == StateDriving)
 {
   // In this state we drive forward while also looking for the
   // opponent using the proximity sensors and checking for the
   // white border.

   if (justChangedState)
   {
     justChangedState = false;
     lcd.print(F("drive"));
   }

   // Check for borders.
   lineSensors.read(lineSensorValues);
   if (lineSensorValues[0] < lineSensorThreshold)
   {
     scanDir = DirectionRight;
     changeState(StateBacking);
   }
   if (lineSensorValues[2] < lineSensorThreshold)
   {
     scanDir = DirectionLeft;
     changeState(StateBacking);
   }

   // Read the proximity sensors to see if know where the
   // opponent is.
   proxSensors.read();
   uint8_t sum = proxSensors.countsFrontWithRightLeds() + proxSensors.countsFrontWithLeftLeds();
   int8_t diff = proxSensors.countsFrontWithRightLeds() - proxSensors.countsFrontWithLeftLeds();

   if (sum >= 4 || timeInThisState() > stalemateTime)
   {
     // The front sensor is getting a strong signal, or we have
     // been driving forward for a while now without seeing the
     // border.  Either way, there is probably a robot in front
     // of us and we should switch to ramming speed to try to
     // push the robot out of the ring.
     motors.setSpeeds(rammingSpeed, rammingSpeed);

     // Turn on the red LED when ramming.
     ledRed(1);
   }
   else if (sum == 0)
   {
     // We don't see anything with the front sensor, so just
     // keep driving forward.  Also monitor the side sensors; if
     // they see an object then we want to go to the scanning
     // state and turn torwards that object.

     motors.setSpeeds(forwardSpeed, forwardSpeed);

     if (proxSensors.countsLeftWithLeftLeds() >= 2)
     {
       // Detected something to the left.
       scanDir = DirectionLeft;
       changeState(StateScanning);
     }

     if (proxSensors.countsRightWithRightLeds() >= 2)
     {
       // Detected something to the right.
       scanDir = DirectionRight;
       changeState(StateScanning);
     }

     ledRed(0);
   }
   else
   {
     // We see something with the front sensor but it is not a
     // strong reading.

     if (diff >= 1)
     {
       // The right-side reading is stronger, so veer to the right.
       motors.setSpeeds(veerSpeedHigh, veerSpeedLow);
     }
     else if (diff <= -1)
     {
       // The left-side reading is stronger, so veer to the left.
       motors.setSpeeds(veerSpeedLow, veerSpeedHigh);
     }
     else
     {
       // Both readings are equal, so just drive forward.
       motors.setSpeeds(forwardSpeed, forwardSpeed);
     }
     ledRed(0);
   }
 }

 decoder.service();

 // Turn on the yellow LED if a message is active.
 ledYellow(messageActive);

 // Turn on the red LED if we are in the middle of receiving a
 // new message from the remote.  You should see the red LED
 // blinking about 9 times per second while you hold a remote
 // button down.
 ledRed(decoder.criticalTime());

 if (decoder.criticalTime())
 {
   // We are in the middle of receiving a message from the
   // remote, so we should avoid doing anything that might take
   // more than a few tens of microseconds, and call
   // decoder.service() as often as possible.
 }
 else
 {
   // We are not in a critical time, so we can do other things
   // as long as they do not take longer than about 7.3 ms.
   // Delays longer than that can cause some remote control
   // messages to be missed.

   processRemoteEvents();
 }

 // Check how long ago the current message was last verified.
 // If it is longer than the timeout time, then the message has
 // expired and we should stop executing it.
 if (messageActive && (uint16_t)(millis() - lastMessageTimeMs) > messageTimeoutMs)
 {
   messageActive = false;
   stopCurrentCommand();
 }
}
uint16_t timeInThisState()
{
 return (uint16_t)(millis() - stateStartTime);
}

// Changes to a new state.  It also clears the LCD and turns off
// the LEDs so that the things the previous state were doing do
// not affect the feedback the user sees in the new state.
void changeState(uint8_t newState)
{
 state = (State)newState;
 justChangedState = true;
 stateStartTime = millis();
 ledRed(0);
 ledYellow(0);
 ledGreen(0);
 lcd.clear();
 displayCleared = true;
}

// Returns true if the display has been cleared or the contents
// on it have not been updated in a while.  The time limit used
// to decide if the contents are staled is specified in
// milliseconds by the staleTime parameter.
bool displayIsStale(uint16_t staleTime)
{
 return displayCleared || (millis() - displayTime) > staleTime;
}

// Any part of the code that uses displayIsStale to decide when
// to update the LCD should call this function when it updates the
// LCD.
void displayUpdated()
{
 displayTime = millis();
 displayCleared = false;
}
void processRemoteEvents()
{
 if (decoder.getAndResetMessageFlag())
 {
   // The remote decoder received a new message, so record what
   // time it was received and process it.
   lastMessageTimeMs = millis();
   messageActive = true;
   processRemoteMessage(decoder.getMessage());
 }

 if (decoder.getAndResetRepeatFlag())
 {
   // The remote decoder receiver a "repeat" command, which is
   // sent about every 109 ms while the button is being held
   // down.  It contains no data.  We record what time the
   // repeat command was received so we can know that the
   // current message is still active.
   lastMessageTimeMs = millis();
 }
}

boolean processRemoteMessage(const uint8_t * message)
{
   bool rushb;
rushb = false;
 // Print the raw message on the first line of the LCD, in hex.
 // The first two bytes are usually an address, and the third
 // byte is usually a command.  The last byte is supposed to be
 // the bitwise inverse of the third byte, and if that is the
 // case, then we don't print it.
 lcd.clear();
 char buffer[9];
 if (message[2] + message[3] == 0xFF)
 {
   sprintf(buffer, "%02X%02X %02X ",
     message[0], message[1], message[2]);
 }
 else
 {
   sprintf(buffer, "%02X%02X%02X%02X",
     message[0], message[1], message[2], message[3]);
 }
 lcd.print(buffer);

 // Go to the next line of the LCD.
 lcd.gotoXY(0, 1);

 // Make sure the address matches what we expect.
 if (message[0] != remoteAddressByte0 ||
   message[1] != remoteAddressByte1)
 {
   lcd.print(F("gud addr"));
   return true;
   //rushb = true;
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 }
 else{return false;}

 // Make sure that the last byte is the logical inverse of the
 // command byte.
 if (message[2] + message[3] != 0xFF)
 {
   lcd.print(F("bad cmd"));
   return false;
 }

 stopCurrentCommand();
 processRemoteCommand(message[2]);
}

// Start running the new command.
void processRemoteCommand(uint8_t command)
{
 switch(command)
 {
 case remoteUp:
   lcd.print(F("up"));
   motors.setSpeeds(400, 400);
   break;

 case remoteDown:
   lcd.print(F("down"));
   motors.setSpeeds(-400, -400);
   break;

 case remoteLeft:
   lcd.print(F("left"));
   motors.setSpeeds(-250, 250);
   break;

 case remoteRight:
   lcd.print(F("right"));
   motors.setSpeeds(250, -250);
   break;

 case remoteStopMode:
   lcd.print(F("stop"));
   break;

 case remoteEnterSave:
   lcd.print(F("enter"));
   break;

 case remoteVolMinus:
   lcd.print(F("vol-"));

   break;

 case remoteVolPlus:
   lcd.print(F("vol+"));
   break;

 case remotePlayPause:
   lcd.print(F("play"));
   break;

 case remoteSetup:
   lcd.print(F("setup"));
   break;

 case remoteBack:
   lcd.print(F("back"));
   break;

 case remote0:
   lcd.print(F("0"));
   break;

 case remote1:
   lcd.print(F("1"));
   buzzer.playNote(NOTE_C(4), 200, 15);
   break;

 case remote2:
   lcd.print(F("2"));
   buzzer.playNote(NOTE_D(4), 200, 15);
   break;

 case remote3:
   lcd.print(F("3"));
   buzzer.playNote(NOTE_E(4), 200, 15);
   break;

 case remote4:
   lcd.print(F("4"));
   break;

 case remote5:
   lcd.print(F("5"));
   break;

 case remote6:
   lcd.print(F("6"));
   break;

 case remote7:
   lcd.print(F("7"));
   break;

 case remote8:
   lcd.print(F("8"));
   break;

 case remote9:
   lcd.print(F("9"));
   Serial.println("Hello there MOTHERFUCKERS!!!");
   break;
 }
}

// Stops the current remote control command.  This is called when
// a new command is received or if the current command has
// expired.
void stopCurrentCommand()
{
 motors.setSpeeds(0, 0);
 buzzer.stopPlaying();
}

Z góry dziękuję za pomoc.

Link do komentarza
Share on other sites

Mokkori, co dokładnie według Ciebie miała robić ta linijka? Ogólnie wiesz co robisz, czy trochę wklejasz "na ślepo"? 🙂 W taki sposób to na pewnie nie zadziała, bo źle używasz tej funkcji, którą (chyba) próbujesz sprawdzić w warunku.

Link do komentarza
Share on other sites

W sumie może lepiej podpiąć start pod jeden przycisk a pod inne np załączenie ledów czy jakiś inny bajer. Może w przyszłości rozbudujesz i pod jednym przyciskiem zrobisz wykonywanie programu dla sumo a na innych reczne sterowanie lub coś innego.

Ale wracając do tematu masz prosty przykład który możesz ślepo kopiować, wiadomo wszystko musisz zrobić pod siebie. Tylko pamietaj że w miejscu adresu musisz wpisać adres ir danego przycisku (na necie jest dużo detektorów kodu jak coś) a poniżej wykonywany kod. Mój program służył do włączenia i wyłączenia diody za pomoca jednego przycisku. Analogicznie wers z case'm wystarczy skopiować wpisać adres i co ma się dziać, tylko ilość przycisków na pilocie cię ogranicza.

 #include <IRremote.h>
#define irPin 2
IRrecv irrecv(irPin);
decode_results results;


int stan; 

void setup() {
  Serial.begin(9600);
   irrecv.enableIRIn();


    pinMode(5, OUTPUT);


}

void loop() {
  if (irrecv.decode(&results)) {

     switch (results.value) {
        case 0xFFA25D:
           Serial.println("1");
          stan = !stan;
           digitalWrite(5, stan);
           delay(250);
           break;



     }


  irrecv.resume();

}
}
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.