wireless RF Arduino with digital compass

February 6, 2010 | Filed Under Blog, Installation Art, Sound Sculpture, physical computing 

I just wrote and tried out the code with hardware for wireless (RF) transmitting from an Arduino with a digital compass to other arduinos with LEDs.

Here is the code for the transmitter (sending to 3 different Arduinos).  The code is set up (the x and y variables) to only send a message out for a given degree range once . . . so you must go to another degree range and come back for the message to be sent again from a given degree range.  This insures that LEDs (or solenoids in the instance of my installation work) are not continuously fired when the compass is left facing one direction with no one around turning it.

#include <Wire.h>
#include <VirtualWire.h> // http://www.open.com.au/mikem/arduino/VirtualWire-1.4.zip

int HMC6352Address = 0x42;
// This is calculated in the setup() function
int slaveAddress;
int ledPin = 13;
boolean ledState = false;
byte headingData[2];
int i, headingValue;

int x = 0;
int y = 0;

void setup()
{
//digital compass setup
// Shift the device's documented slave address (0x42) 1 bit right
// This compensates for how the TWI library only wants the
// 7 most significant bits (with the high bit padded with 0)
slaveAddress = HMC6352Address >> 1;   // This results in 0x21 as the address to pass to TWI
//Serial.begin(9600);
pinMode(ledPin, OUTPUT);      // Set the LED pin as output
Wire.begin();

//transmitter setup
vw_setup(2000);     // Bits per sec
}

void loop()
{
 // Flash the LED on pin 13 just to show that something is happening
 // Also serves as an indication that we're not "stuck" waiting for TWI data
 ledState = !ledState;
 if (ledState) {
 digitalWrite(ledPin,HIGH);
 }
 else
 {
 digitalWrite(ledPin,LOW);
 }
 // Send a "A" command to the HMC6352
 // This requests the current heading data
 Wire.beginTransmission(slaveAddress);
 Wire.send("A");              // The "Get Data" command
 Wire.endTransmission();
 delay(10);                   // The HMC6352 needs at least a 70us (microsecond) delay
 // after this command.  Using 10ms just makes it safe
 // Read the 2 heading bytes, MSB first
 // The resulting 16bit word is the compass heading in 10th's of a degree
 // For example: a heading of 1345 would be 134.5 degrees
 Wire.requestFrom(slaveAddress, 2);        // Request the 2 byte heading (MSB comes first)
 i = 0;
 while(Wire.available() && i < 2)
 {
 headingData[i] = Wire.receive();
 i++;
 }
 headingValue = headingData[0]*256 + headingData[1];  // Put the MSB and LSB together
 /*
 Serial.print("Current heading: ");
 Serial.print(int (headingValue / 10));     // The whole number part of the heading
 Serial.print(".");
 Serial.print(int (headingValue % 10));     // The fractional part of the heading
 Serial.println(" degrees");
 */
 headingValue = (int (headingValue / 10));
 //Serial.println(int (headingValue)); //debugging

 const char *mymessage = "Z";

 if ((headingValue >= 1) && (headingValue <= 179)){
 mymessage = "A";
 y = 1;
 }
 else if ((headingValue >= 180) && (headingValue <= 250)){
 mymessage = "B";
 y = 2;
 }
 else {
 mymessage = "C";
 y = 3;
 }

 if (x != y){
 digitalWrite(13, true);  // turn on LED to show transmitting
 vw_send((uint8_t *)mymessage, strlen(mymessage));  // transmit message
 vw_wait_tx(); // Wait until the whole message is gone
 digitalWrite(13, false);  // turn off LED to show transmitting is done
 x = y;
 //Serial.println(mymessage); //debugging
 }
 else{
 }

 delay(100);   //not sure how short I can make this yet???
}

=======================================================

Here is the code for the receivers (change what is commented out, ‘A’, ‘B’, or ‘C’ message at the end, according to which of the three Arduinos you load the sketch up to):

// receiver.pde

#include <VirtualWire.h> // http://www.open.com.au/mikem/arduino/VirtualWire-1.4.zip

char inString[32];
int inCount;

void setup()
{

 pinMode(9, OUTPUT);        // sets the LED pin to be an output

 ////// serial code is commented out because this application does  //////
 ////// not require a computer - remove comment to send to computer //////
 //Serial.begin(9600);    
 //Serial.println("setup");

 vw_setup(2000);     // Bits per sec

 vw_rx_start();       // Start the receiver PLL running
}

void loop()
{

 uint8_t buf[VW_MAX_MESSAGE_LEN];
 uint8_t buflen = VW_MAX_MESSAGE_LEN;
 inCount = 0;

 if (vw_get_message(buf, &buflen)) // Non-blocking
 {
 int i;
 digitalWrite(13, true); // turn on LED to show received good message
 // Message with a good checksum received, dump it.
 //Serial.print("Got: ");    
 for (i = 0; i < buflen; i++)
 {
 //Serial.print(buf[i]);
 //Serial.print(" ");
 inString[inCount] = buf[i];
 inCount++;
 }
 //Serial.println("");

 ////// if statements comparing incoming message //////
 ////// comment out letters for different sculptures //////
/*
 if (strcmp(inString, "A") == 0){
 digitalWrite(9, true);
 delay (500);
 digitalWrite(9, false);
 }

 if (strcmp(inString, "B") == 0){
 digitalWrite(9, true);
 delay (500);
 digitalWrite(9, false);
 }
*/        
 if (strcmp(inString, "C") == 0){
 digitalWrite(9, true);
 delay (500);
 digitalWrite(9, false);
 }

 digitalWrite(13, false); // turn off LED to show done
 }
}

Comments

Leave a Reply