Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

My New Project

Status
Not open for further replies.
Decorate the box with the tips of various LEDs but one really is an IR LED. It can work like a TV remote to activate an IR receiver and use it to turn on a group of 8 tiny LEDs in a 2x4 array across the room.

National Semiconductors used to make IR transmitter/IR Receiver pairs of chips with 16 "channels".
I can send you a pair if needed (I think I have 8 pairs). Super easy.
 
Taking the advice that I was kindly offered on this forum I decided to take the microcontroller route.

I bought two Arduino UNOs and set about trying to write the TX and RX programmes (sketches). However, to make it easy on myself I decided to initially just try and remotely switch two LEDs ON and OFF using push buttons. The idea being that if I could get that to work then I could expand / extrapolate the sketches to light 8 LEDs and replace the push buttons with magnetic sensors.

So on paper my initial requirements are reasonably simple, as follows:

1. Press button 1 on the TX and LED 1 lights on the RX. Release button 1 and the LED 1 goes out.

2. Press button 2 on the TX and LED 2 lights on the RX. Release button 2 and the LED 2 goes out.

3. Press buttons 1 and 2 together and both LEDs light. Release both buttons and both LEDs go out.

The TX and RX sketches I have written do work and the LEDs light as detailed above, but with one slight problem. When I press button 1, LED 1 lights but flashes, and this is the same for the operation of button 2 / LED 2. Also, if I press both buttons (1 & 2) together, LEDs 1 & 2 flash alternatively (in sequence). Although this problem is not a show stopper, because it gives me the information I require (in a flashing form), it would, however, be nice if I could get the LEDs to come ON and stay ON until the buttons are released....i.e. not flash.

I have tried several options to rectify the problem, without success. I'm pretty sure it has something to do with the loop function, however, it's a bit beyond me at this stage.

Some additional notes:

1. When I add the braces to the TX and RX "else" statements (please see sketches below) the LEDs still flash when the individual buttons are pressed, but when both buttons are pressed together only one LED (could be either one) will light. That seems to be linked to the flash cycle. So this doesn't work.

2. I have used the VirtualWire library and not RadioHead library for this simple project, and it does work.

Note: If I use the RadioHead library and make the necessary adjustments to the TX and RX sketches (that I think are required) I get a similar problem to the one described above (with the braces). I can switch ON the LEDs individually, but not together. So this doesn't work.

3. For the remote connections I am using a 433Mhz Superheterodyne 3400 RF Transmitter Receiver pair.

My TX and RX sketches are detailed below, and after many days of experimenting and a lot of head scratching this is the closest I can get to my requirements.

Transmitter Sketch:

#include <VirtualWire.h>

const int transmit_pin = 12;

int button1 = 2;

int button2 = 3;

int DL=1000;



void setup(){

// Initialise the IO and ISR

vw_set_tx_pin(transmit_pin);

pinMode(button1, INPUT);

pinMode(button2, INPUT);

vw_setup(2000); // Bits per sec

}

byte count = 1;


void loop(){

char msg1[2] = {'h'};

char msg2[2] = {'j'};

if(digitalRead(button1) == 1){

vw_send((uint8_t *)msg1, 1); // change this number according to the sensor values

vw_wait_tx(); // Wait until the whole message is gone

delay(DL);

}

if(digitalRead(button2) == 1){

vw_send((uint8_t *)msg2, 1); // change this number according to the sensor values

vw_wait_tx(); // Wait until the whole message is gone

delay(DL);

}

else

digitalWrite(button1,LOW);

digitalWrite(button2,LOW);

}



Receiver Sketch:

#include <VirtualWire.h>

const int receive_pin = 11;

int LED1 = 2;

int LED2 = 3;

int DT=1000;


void setup(){

delay(DT);

Serial.begin(9600); // Debugging only

Serial.println("setup");

// Initialise the IO and ISR

vw_set_rx_pin(receive_pin);

vw_set_ptt_inverted(true); // Required for DR3100

vw_setup(2000); // Bits per sec

vw_rx_start(); // Start the receiver PLL running

pinMode(LED1, OUTPUT);

pinMode(LED2, OUTPUT);

}



void loop(){

uint8_t buf[VW_MAX_MESSAGE_LEN];

uint8_t buflen = VW_MAX_MESSAGE_LEN;

if (vw_get_message(buf, &buflen)){ // Non-blocking

int i;

// Message with a good checksum received, dump it.

Serial.print("Got: ");

for (i = 0; i < buflen; i++){

char c = (buf);

if( c == 'h'){

digitalWrite(LED1 , HIGH);

Serial.print(c);

Serial.print(' ');

delay(DT);

}

if( c == 'j'){

digitalWrite(LED2 , HIGH);

Serial.print(c);

Serial.print(' ');

delay(DT);

}

else

digitalWrite(LED1,LOW);

digitalWrite(LED2,LOW);

}

}

}

Because of my lack of experience in this field I am not sure if I am close to a final solution or completely off course. So any help / guidance will be greatly appreciated.

Bill
 
If you put the word code in [. ] brackets then a closing [ / same word "code" ] with the slash, we can read your code with white space formatting.

Code:
#include <VirtualWire.h>

const int transmit_pin = 12;

int button1 = 2;

int button2 = 3;

int DL=1000;



void setup(){

// Initialise the IO and ISR

vw_set_tx_pin(transmit_pin);

pinMode(button1, INPUT);

pinMode(button2, INPUT);

vw_setup(2000); // Bits per sec

}

byte count = 1;


void loop(){

char msg1[2] = {'h'};

char msg2[2] = {'j'};

if(digitalRead(button1) == 1){

vw_send((uint8_t *)msg1, 1); // change this number according to the sensor values

vw_wait_tx(); // Wait until the whole message is gone

delay(DL);

}

if(digitalRead(button2) == 1){

vw_send((uint8_t *)msg2, 1); // change this number according to the sensor values

vw_wait_tx(); // Wait until the whole message is gone

delay(DL);

}

else

digitalWrite(button1,LOW);

digitalWrite(button2,LOW);

}



Receiver Sketch:

#include <VirtualWire.h>

const int receive_pin = 11;

int LED1 = 2;

int LED2 = 3;

int DT=1000;


void setup(){

delay(DT);

Serial.begin(9600); // Debugging only

Serial.println("setup");

// Initialise the IO and ISR

vw_set_rx_pin(receive_pin);

vw_set_ptt_inverted(true); // Required for DR3100

vw_setup(2000); // Bits per sec

vw_rx_start(); // Start the receiver PLL running

pinMode(LED1, OUTPUT);

pinMode(LED2, OUTPUT);

}



void loop(){

uint8_t buf[VW_MAX_MESSAGE_LEN];

uint8_t buflen = VW_MAX_MESSAGE_LEN;

if (vw_get_message(buf, &buflen)){ // Non-blocking

int i;

// Message with a good checksum received, dump it.

Serial.print("Got: ");

for (i = 0; i < buflen; i++){

char c = (buf);

if( c == 'h'){

digitalWrite(LED1 , HIGH);

Serial.print(c);

Serial.print(' ');

delay(DT);

}

if( c == 'j'){

digitalWrite(LED2 , HIGH);

Serial.print(c);

Serial.print(' ');

delay(DT);

}

else

digitalWrite(LED1,LOW);

digitalWrite(LED2,LOW);

}

}

}
 
You are alternately "looking at" and processing each switch, so you get an alternating effect.

I'd guess the RF comms library you are using is adding a lot of overhead to each transmission; simple RF modules need a preamble sending before any data, to allow the receiver to settle, plus some amount of synchronising for the start of actual data, and probably error detection. That means each transmission is probably 100 - 300mS long or something like that, depending on the data rate.

Your program stops dead at the wait_tx stage for that to happen, each time through the loop when anything is sent.


If you read both switches to start with, then send different data values for each combination, you can have any number of inputs / switches working together smoothly.

eg. If the are both off (but were pressed last time round the loop), send "0".

If the first button is pressed, send 1; for the second one send 2; for both send 3.
The numbers could be text or binary, as long as you match them in the receiver.

Set the appropriate output combination at the receiver, depending on the character or combination of bits is received, plus a timeout to turn them off after a short time with no data.

Or whichever combination of characters you prefer, to represent things. We just use the input port byte, ANDed with a mask to disable any unused inputs.

(Our gear does not use library functions, all the TX is done in the main program, transmitting is buffered in the background & it allows for failed transmissions etc; but the principles are similar)
 
To add to the above, your main loop could be something like,
Code:
void loop(){
char send=0;
    if(digitalRead(button1) == 1){
        send=send+1;
    }
    if(digitalRead(button2) == 1){
        send=send+2;
    }
    vw_send(send+'0', 1); // send ascii 0,1,2 or 3
    vw_wait_tx(); // Wait until the whole message is gone
    delay(20);
}

And on the other end you'd have something like,
Code:
void loop(){
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

    if (vw_get_message(buf, &buflen)){ // Non-blocking
        int i;

        // Message with a good checksum received, dump it.

        Serial.print("Got: ");
        char c = buff[0];
        Serial.println(c);
        c=c-'0';

        if(c & 1){
            digitalWrite(LED1 , HIGH);
        }else{
            digitalWrite(LED1,LOW);
        }
        if(c & 2){
            digitalWrite(LED2 , HIGH);
        }else{
            digitalWrite(LED2,LOW);
        }
    }
}

I'm not familiar with this particular library so may have it wrong. I assume that any string received is terminated with a zero.
Note, it makes no sense to write to a pin that's an input and no delay is required on the receive end.

Hope that makes a little sense.

Mike.
Edit, had too many braces in receive code.
 
Last edited:
Looking at this again, it looks like vw_send() requires a char pointer to the string to send.
If so, then this should work,
Code:
void loop(){
char send[2]={'0',0};    //buffer contains ascii zero followed by actual zero
    if(digitalRead(button1) == 1){
        send[0]=send[0]+1;
    }
    if(digitalRead(button2) == 1){
        send[0]=send[0]+2;
    }
    vw_send((uint8_t *)send, 2); //not sure if this cast is necessary. 
    vw_wait_tx(); // Wait until the whole message is gone
    delay(20);
}

Mike.
 
Hi Mike,

Absolutely fantastic......works like a dream! I can't thank you enough.

There was only one minor adjustment I had to make to your suggested RX sketch - char c = buff;

I have also expanded the sketches to accommodate 8 buttons (sensors), and I have tried the circuitry with Hall Effects ICs instead of buttons...everything worked as I had hoped.

Lastly, many thanks to everyone who provided suggestions / advice on this project.......it was all greatly appreciated.

Stay safe!

Bill
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top