Hey, is it possible to make sort of a Queue??
Basically I am trying to make a robot and I am still figuring out what he would do. My current idea is that it will be like a car that you will have five buttons, one to go forward one backwards one to turn right one to turn left and one to execute the commands.
Now my problem is that I have no idea how to program such a thing so I would assume I would need to create a couple of functions and every time I press it would be saved in a "queqe" and when I press the execute botton the queqe will be played.
This is an example that might help you. It shouldn't be to hard to adapt it to your needs. Just add a "command" field to the QueueEntry struct in Buzzer.h. Arduino Buzzer Queue
This seems to work with a paperclip on my 2560. If not, it should give a general idea of how one might approach a queue:
#define NUM_BUTTONS 5
#define MAX_QUEUE_SIZE 20
#define BTN_READ_INTERVAL 30 //30mS button read interval
#define CMD_FWD 0
#define CMD_REV 1
#define CMD_RGT 2
#define CMD_LFT 3
#define CMD_EXECUTE 4
const byte Commands[NUM_BUTTONS] =
{
CMD_FWD,
CMD_REV,
CMD_RGT,
CMD_LFT,
CMD_EXECUTE
};
const int pinFwdButton = 9;
const int pinRevButton = 10;
const int pinRgtButton = 11;
const int pinLftButton = 12;
const int pinExecute = 13;
const int buttonPins[NUM_BUTTONS] =
{
pinFwdButton,
pinRevButton,
pinRgtButton,
pinLftButton,
pinExecute
};
int lastButtons[NUM_BUTTONS];
int currButtons[NUM_BUTTONS];
byte queueCmds[MAX_QUEUE_SIZE];
byte queueIdx;
void setup()
{
byte
i;
//setup the pins as inputs with pull-ups
for( i=0; i<NUM_BUTTONS; i++ )
pinMode( buttonPins[i], INPUT_PULLUP );
//read the current state of the button inputs and record as "last" for later
for( i=0; i<NUM_BUTTONS; i++ )
{
currButtons[i] = (digitalRead( buttonPins[i] ) == HIGH)?1:0;
lastButtons[i] = currButtons[i];
}//for
queueIdx = 0;
Serial.begin(9600);
while(!Serial);
}//setup
void loop()
{
if( ReadButtons() == true )
{
//is there anything in the queue?
if( queueIdx > 0 )
GoRunQueue( &queueIdx );
//when finished running the queue, reset the queue pointer back to zero
queueIdx = 0;
}//if
}//loop
bool ReadButtons( void )
{
static unsigned long
timeButton = 0;
unsigned long
timeNow;
bool
done;
int
i;
//is it time to read the buttons yet?
timeNow = millis();
if( (timeNow - timeButton) < BTN_READ_INTERVAL )
return false;
timeButton = timeNow;
//read all the buttons
for( i=0; i<NUM_BUTTONS; i++ )
currButtons[i] = (digitalRead( buttonPins[i] ) == HIGH)?1:0;
//this tells us if we saw the execute button pressed (true means yes...)
done = false;
//check for any changes
for( i=0; i<NUM_BUTTONS; i++ )
{
//an XOR of the curr with the last; '1' means they're not the same
if( currButtons[i] ^ lastButtons[i] )
{
//change detected; was it a high to low ((curr == 0, last == 1)?
if( currButtons[i] == 0 && lastButtons[i] == 1 )
{
//is this the execute button?
if( i==NUM_BUTTONS-1 )
done = true;
else
{
//let you see what's going on...
Serial.print("Got button "); Serial.println(i);
//add button to the queue (if there's room...)
if( queueIdx < (MAX_QUEUE_SIZE-1) )
queueCmds[queueIdx++] = Commands[i];
}//else was not execute button
}//if was button press "down"
}//if not same as last
}//for buttons
//make the last equal to the current for the next time we pass through
for( i=0; i<NUM_BUTTONS; i++ )
lastButtons[i] = currButtons[i];
//return true (execute button hit)
//or false (any other -- or no -- button hit)
return done;
}//ReadButtons
//just show the queue with some prints to the console
void GoRunQueue( byte *queueNum )
{
for( int i=0; i < *queueNum; i++ )
{
switch( queueCmds[i] )
{
case CMD_FWD:
Serial.println( "FORWARD" );
break;
case CMD_REV:
Serial.println( "REVERSE" );
break;
case CMD_RGT:
Serial.println( "TURN RIGHT" );
break;
case CMD_LFT:
Serial.println( "TURN LEFT" );
break;
}//switch
}//for
}//GoRunQueue
A queue can be as simple as an array that holds the series of steps. There would be two variables, one that identifies the front of the queue and another that identifies the end.
When the queue is empty they will both have the same value (0).
To add a value put in the array element identified by the front variable and increment that variable.
To read the oldest value (i.e. the one that was put in the array first) read the element identified by the end variable and increment it.
If either the front or end variable reaches a value that is beyond the end of the array just set it back to 0
If the front variable is one less than the end variable the array will be full. If (say) the array has 16 variables just remember that element 15 is right behind element 0
Cool thx, I am kinda new to this so could you give me an example??
Robin2:
A queue can be as simple as an array that holds the series of steps. There would be two variables, one that identifies the front of the queue and another that identifies the end.
When the queue is empty they will both have the same value (0).
To add a value put in the array element identified by the front variable and increment that variable.
As a queue element, consider a struct{} with members... ‘action’ and ‘durationMs’
Then as you step through the ‘queue’ array of structs, you know what to do, and how long to do it for...