The 10 Commandments of Wireless Communications

Posted on February 18th, 2009

This is a repost from Mike Fahrion of BB-Electronics which has a great technical library.  I’m putting it up here because it’s so good, I’d hate for it to disappear off the web.

Follow these rules, and you’ll have happy Wireless.  Ignore them, and experience BER!

10 Commandments of Wireless Communications

(more…)

Some sample code to ignore!

Posted on February 13th, 2009

/*Pier Piling Pivot Arduino control program
by Earl Stirling for the explOratorium
installed on Fort Mason Piers
*/
/*
version 0.813
07/jan/2009
*/

/*This is a state machine.
This program counts on tight(ish) loops with no stalling.
I recommend using anything that stalls, the functions delay() or delayMicroseconds(),
they’re unnecessary, and you might miss a timeout
*/

/*

*/

//These are the states that the machine can be in.
//Entries in this enum should match the state_table pointer.
enum
{
WTG_FOR_BUTTONPRESS = 0,
ASCENDING,
UP,
DESCENDING,
DOWN,
ERROR,
curr_state_LIMIT
}
curr_state, prev_state = WTG_FOR_BUTTONPRESS;

//This table contains a pointer to the function to call in each state.
//These must match the enums for curr_state
void (*state_table[curr_state_LIMIT])() =
{
WtgForButtonpress,
Ascending,
Up,
Descending,
Down,
Error
};

//these constant defines are the correct place to change timeout values, pin values, etc.
#define KEEPUPTIME   120           //should be 120, change before deployment // timeout in seconds to keep the piling up
#define HOLDDOWNTIME 4         // time in seconds to keep the piling down before next ascent
#define MOVEMENTTIME 60        // time in seconds for maximum time to move the piling

#define BUTTONPINNUMBER     2  //the pin that the button is attached to
#define UPPERLIMITPINNUMBER 3  //the pin that the upper limit switch is attached to
#define LOWERLIMITPINNUMBER 4  //the pin that the lower limit switch is attached to
#define INSECTORPINNUMBER   5  //the pin for detecting that the mechanism is in normal operating range
#define RAISEMOTORPINNUMBER 6 //the pin for the relay to raise the piling
#define LOWERMOTORPINNUMBER 7 //the pin for the relay to lower the piling
//#define MOTORBRAKEPINNUMBER 8 //the pin for the relay to release the motor brake

#define ledPin  13  //the pin attached to the LED

long StartMovementTime;

int error_code, spinner = 0, thistime = 0;

//Limit switch values
enum {
MADE,
NOTMADE}
UpperLimitSwitch,
LowerLimitSwitch,
InSectorSensor;

//UI button value
enum {
PRESSED, NOTPRESSED}
Button;

//MOTOR CONTACTS!
//which motor contacts you’re calling
typedef enum {
RAISE, LOWER}
Motor_Contacts;

#define RAISE RAISEMOTORPINNUMBER
#define LOWER LOWERMOTORPINNUMBER
//#define brake MOTORBRAKEPINNUMBER

//motor actions you’re calling for
#define OFF  0
#define ON   1

//TIMERS!
//Timer values (should make this an array of type timertypes)
//int UpCountdownTimerValue, HOLDDOWNTIMERValue, ReversalCounterValue;
//TimerState UpCountdownTimer, HoldDownTimer;

//Actions you can call for the Timers
typedef enum {
START, RESET, EXPIRE, CHECK}
Timer_Actions;
#define START 0
#define RESET 1
#define EXPIRE 2
#define CHECK 3

//enumeration of the types of timers
typedef enum {
HOLDDOWN, KEEPUP, MOVEMENT, TIMERS_LIMIT}
Timers_new;
#define HOLDDOWN 0
#define KEEPUP 1
#define MOVEMENT 2

//states in which the timers can exist
typedef enum {
EXPIRED, CURRENT}
TimerState;
#define EXPIRED 0
#define CURRENT 1

void setup()
{
Serial.begin(9600); //setup serial output port
delay(3000);
//Send a string of CTRL-R’s to reset the LCD to 9600 baud
// for (int i=5000; i != 0 ; i–) {Serial.print(0×12,BYTE); };

// Initialize counters, flash LED’s, turn off outputs

//Initialize LCD display
//first set to 20 characters wide
Serial.print(0×7C,BYTE);
Serial.print(0×03,BYTE);
delay(128);

//then set to 4 lines long
Serial.print(0×7C,BYTE);
Serial.print(0×05,BYTE);
delay(128);

//clear display
Serial.print(0xFE,BYTE);
Serial.print(0×01,BYTE);
delay(128);

//turn display on
Serial.print(0xFE,BYTE);
Serial.print(0×0C,BYTE);
delay(128);

/*
//Set up splash screen for LCD
lcd_cursor(1,1);
Serial.print(”Pier Piling Pivot”);
Serial.print(”version 0.81″);
//delay(128);

//now save the current screen as the splash to the LCD’s NVRAM
Serial.print(0×7C,BYTE);
Serial.print(0×10,BYTE);
//delay(128);
*/
lcd_cursor(1,1);
Serial.print(”Starting setup     “);

pinMode(BUTTONPINNUMBER, INPUT);
pinMode(UPPERLIMITPINNUMBER, INPUT);
pinMode(LOWERLIMITPINNUMBER, INPUT);
pinMode(INSECTORPINNUMBER, INPUT);

pinMode(RAISEMOTORPINNUMBER, OUTPUT);
pinMode(LOWERMOTORPINNUMBER, OUTPUT);
//pinMode(MOTORBRAKEPINNUMBER, OUTPUT);

pinMode(ledPin, OUTPUT);

MotorContact (LOWER, OFF);
MotorContact (RAISE, OFF);

lcd_cursor(1,1);
Serial.print(”Done with setup    “);
};

// * * Begin State Functions * *

void Down()
{
/* Piling is down, wait for the hold down timeout, then
transition to waiting for someone to press the button.*/
poll();

for (int i=(HOLDDOWNTIME - 1); i != 0 ; i–)
{
//delay(128);
//move to 0,0
lcd_cursor(2,1);

Serial.print(”Hold Down: “);
Serial.print(i);
Serial.print(”      “);
}
curr_state = WTG_FOR_BUTTONPRESS;
}

void Error()
{
//digitalWrite (brake,LOW);

lcd_cursor(2,1);
Serial.print(”Error “);Serial.print(error_code);Serial.print(”             “);
switch (error_code)
{
case 2 :   lcd_cursor(4,1);Serial.print(”Movement Sector     “); break;
case 1 : lcd_cursor(4,1);Serial.print(”Movement Timeout    “); break;
};

MotorContact (LOWER, OFF);
MotorContact (RAISE, OFF);
for (int i=error_code; i != 0 ; i–)
{
digitalWrite(ledPin, HIGH);   // sets the LED on
delay(1000);                  // waits for a second
digitalWrite(ledPin, LOW);    // sets the LED off
delay(1000);                  // waits for a second
};
}

void WtgForButtonpress()
{
/* Hang around waiting for some curious kid to press the button. */
//Serial.print(”WtgForButtonpress”);
poll();

if ((InSectorSensor == MADE) and (Button == PRESSED))
{
MotorContact (RAISE,ON);
StartMovementTime = millis();
//lcd_cursor(2,1);Serial.print(”Start Movement Time (sec)”);Serial.print(StartMovementTime/1000);
curr_state = ASCENDING;
}
}

void Ascending()
{
// When the piling reaches the top, stop raising it.
//Serial.print(”Ascending”);
poll();

MovementErrorCheck();
if ((curr_state != ERROR) and (UpperLimitSwitch == MADE))
{
MotorContact(RAISE,OFF);
curr_state = UP;
}
}

void Descending()
{
// When the piling reaches the bottom, stop lowering it.
//Serial.print(”Descending”);
poll();

MovementErrorCheck();
if ((curr_state != ERROR) and (LowerLimitSwitch == MADE))
{
MotorContact(LOWER,OFF);
curr_state = DOWN;
}
}

void Up()
{
/* If the timer expires or the button is pressed, lower
the piling (check that lower switch isn’t hit) .*/
//Serial.print(”Up”);
poll();

for (int i=(KEEPUPTIME - 1); i != 0 ; i–)
{
//delay(128);
lcd_cursor(2,1);Serial.print(”Keep Up: “);
Serial.print(i);
}
if (InSectorSensor == MADE)
{
MotorContact (LOWER,ON);
StartMovementTime = millis();
//lcd_cursor(2,1);Serial.print(”Start Movement Time (sec)”);Serial.print(StartMovementTime/1000);
curr_state = DESCENDING;
}
}

// * * End of State Functions * *

void poll()
{
thistime = (millis()/1000) % 4;
if (spinner != thistime)
{
lcd_cursor(1,20);
spinner = thistime;
//Serial.println(spinner);
switch (spinner)
{
case 0:
//print
Serial.print(”>”);
break;
case 1:
//print an Up arrow
Serial.print(”v”);
break;
case 2:
Serial.print(”<”);
break;
case 3:
Serial.print(”^”);
break;
}
};

if (prev_state != curr_state)
{
lcd_cursor(1,1);
Serial.print(”                   “);
lcd_cursor(1,1);
Serial.print(curr_state);
prev_state = curr_state;
}

if (digitalRead(BUTTONPINNUMBER) == HIGH)
{
if (Button != PRESSED) {lcd_cursor(3,1);Serial.print(”Button is PRESSED   “);}
Button = PRESSED;
}
else
{
if (Button != NOTPRESSED) {lcd_cursor(3,1);Serial.print(”Button is NOT-PRESSED   “);}
Button = NOTPRESSED;
//Serial.print(”Button is NOTPRESSED”);
}

if (digitalRead(UPPERLIMITPINNUMBER) == HIGH)
{
if (UpperLimitSwitch != MADE) {lcd_cursor(3,1);Serial.print(”Upper Limit MADE    “);}
UpperLimitSwitch = MADE;
}
else {
if (UpperLimitSwitch != NOTMADE) {lcd_cursor(3,1);Serial.print(”Upper Limit NOT-MADE    “);}
UpperLimitSwitch = NOTMADE;
//Serial.print(”UpperLimitSwitch is NOTMADE”);
}

if (digitalRead(LOWERLIMITPINNUMBER) == HIGH)
{
if (LowerLimitSwitch != MADE) {lcd_cursor(3,1);Serial.print(”Lower Limit MADE    “);}
LowerLimitSwitch = MADE;
}
else {
if (LowerLimitSwitch != NOTMADE) {lcd_cursor(3,1);Serial.print(”Lower Limit NOT-MADE    “);}
LowerLimitSwitch = NOTMADE;
//Serial.print(”LowerLimitSwitch is NOTMADE”);
}

//Serial.print(”insectorpinnumber is “);Serial.print(digitalRead(INSECTORPINNUMBER));
if (digitalRead(INSECTORPINNUMBER) == HIGH)
{
if (InSectorSensor != MADE) {lcd_cursor(3,1);Serial.print(”In Sector MADE      “);}
InSectorSensor = MADE;
}
else
{
if (InSectorSensor != NOTMADE) {lcd_cursor(3,1);Serial.print(”In Sector NOTMADE   “);}
InSectorSensor = NOTMADE;
}
}

//** Begin Service Functions & Procedures**

//function call to twiddle the contacts
void MotorContact (int contact, int action)
{
//Serial.print(”Setting Motor Contact “); Serial.print(contact);
if (action == ON)
{//digitalWrite (brake,HIGH);
digitalWrite (contact,HIGH);
//Serial.print(” HIGH”);
}
else
{//digitalWrite (brake,LOW);
digitalWrite (contact,LOW);
//Serial.print(” LOW”);
}
};

void MovementErrorCheck()
/*function call to check for errors while moving
will change state to ERROR if there is a movement error,
and throw a code to serial output */
{
//Serial.print((millis()-StartMovementTime)/1000);
if (((millis()-StartMovementTime)/1000) > MOVEMENTTIME)
{
curr_state = ERROR;
error_code = 1;
lcd_cursor(2,1);Serial.print(”Err Movement Timeout”);
};
if (InSectorSensor == NOTMADE)
{
curr_state = ERROR;
error_code = 2;
lcd_cursor(2,1);Serial.print(”Err Out of Range    “);
}
};

void lcd_cursor(int row, int column)
{
int cursor_position, offset;

switch (row)
{
case 1:
offset = 0;
break;
case 2:
offset = 64;
break;
case 3:
offset = 20;
break;
case 4:
offset = 84;
break;
}

cursor_position=offset+column+127;

Serial.print(254,BYTE);
Serial.print(cursor_position,BYTE);
delay(128);
};

// * * Main Loop (”Booooorrrrring!!!!”) * *
void loop()
{
//lcd_cursor(1,1);Serial.print(”Starting loop       “);
/* The heart of the state machine is this one loop.  The function
corresponding to the current state is called once per iteration. */
while (1)
{
state_table[curr_state]();
}
};

© Bang ! Engineering • Powered by Wordpress • Using the Swiss Cool theme.