new project question/advice request

I would like to build a device, based on the knock sensor idea that will flash LEDs when it senses a hit on a steel target that it is attached to. I have seen this done using a piezo transducer and arduino uno, however I would like to separate the LED from the target to avoid breakage. How can I do this as a remote unit with RF. I am new to this and appreciate any guidance.

Rescurat:
How can I do this as a remote unit with RF.

433 MHz modules
nRF2401 modules

I only have experience with nRF24L01+ modules. However I can't see an LED being any more prone to damage than an nRF24.

Also, if any transmitter is inside a metal box the radio signals will not get out.

I got my nRF24s working with this Tutorial

I suggest you use the TMRh20 version of the RF24 library - it solves some problems from the ManiacBug version

The pair of programs in this link may be useful.

...R

Hi,

Welcome to the forum.

What distance do you want to separate the two?
Would just a pair of wires to the LED do?
Place the arduino in a box away from the plate, safe from damage.
Shielded leads to the shock sensor.

Tom... :slight_smile:

Robin2:
I only have experience with nRF24L01+ modules. However I can't see an LED being any more prone to damage than an nRF24.

Also, if any transmitter is inside a metal box the radio signals will not get out.

I got my nRF24s working with this Tutorial

I suggest you use the TMRh20 version of the RF24 library - it solves some problems from the ManiacBug version

The pair of programs in this link may be useful.

...R

The project with the Tx unit will be mounted to the back of the target and housed in a plastic project enclosure. The original knock sensor that I'm using as a basis for this build mounted the LED on a Popsicle stick at the edge of the target where it was vulnerable to being fragged. I want to move the LED to the Rx unit that can be remote from the target.

TomGeorge:
Hi,

Welcome to the forum.

What distance do you want to separate the two?
Would just a pair of wires to the LED do?
Place the arduino in a box away from the plate, safe from damage.
Shielded leads to the shock sensor.

Tom... :slight_smile:

I would like to have the option to move the Rx/indicator portion beyond a few yards, any wiring would be vulnerable to being fragged. The Tx/sensing unit will be protected attached to the back of the target.

ieee488:
433 MHz modules
nRF2401 modules

Are either of these units multi channel, I would like to be able to set up multiple pairs to use on different targets. How would you go about preventing cross talk? Would it be sufficient to alter the "signal" sent to allow multiple Tx/Rx pairs for different targets? Also, how do I go about combining sketches to add rf function?

I have a working knock sensor, what I would like to do is basically move the LED to the RX unit replacing it with the transmitter and replacing the Piezo input with the receiver.

You can use nRF24s to communicate with several other nRF24s separately by giving each a different “address” or with several at the same time by giving them all the same address.

The pair of programs I linked to earlier was abstracted from a system for controlling several model trains.

…R

I think I figured this out with just one small glitch. The LED on the receive module blinks continuously in the absence of a signal. How do I keep the LED in a low sate until a signal is received then go Low again after?

/*
Target Sensor recieve module.
------------------------------------------------------------- */

#define rfReceivePin A0 //RF Receiver pin = Analog pin 0
#define ledPin 9 //Onboard LED = digital pin 9

unsigned int data = 0; // variable used to store received data
const unsigned int upperThreshold = 70; //upper threshold value
const unsigned int lowerThreshold = 50; //lower threshold value

void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}

void loop() {
data = analogRead(rfReceivePin); //listen for data on Analog pin 0

if (data > upperThreshold) {
digitalWrite(ledPin, LOW); //If a LOW signal is received, turn LED OFF
Serial.println(data);
}

if (data < lowerThreshold) {
digitalWrite(ledPin, HIGH); //If a HIGH signal is received, turn LED ON
Serial.println(data);
}
}

Rescurat:
How do I keep the LED in a low sate until a signal is received then go Low again after?

Rather than control the LED directly you should use the received signal to set or clear the state of a variable and use the state of that variable to control the LED.

You probably also need to clear or set the variable only when the received signal changes.

...R

Unfortunately I am very new to this and not sure how to do that. I've gotten as far as I have by simply combining the knock sensor and TX RX sketches. I thought that is what I was doing by setting threshold limits and listening for data

Hi

Good to see you have got some code working and the Tx and Rx communicating.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Both Tx and Rx codes would be appreciated.

Thanks… Tom… :slight_smile:

Thanks Tom, here is the code properly posted, both tx and rx. The tx unit is working as planned, and the rx unit is receiving the signal and operating as planned, however there is something causing the rx unit led to flash in the interim.

Tx code

/*
Target Sensor Transmit module.
  ------------------------------------------------------------- */
const int ledPin = 9;      // led connected to digital pin 9
const int knockSensor = A0; // the piezo is connected to analog pin 0
const int rfTransmitPin = 4; // rf transmitter connected to pin 4
const int threshold = 400;  // threshold value to decide when the detected sound is a knock or not

int sensorReading = 0;      // variable to store the value read from the sensor pin
int ledState = LOW;         // variable used to store the last LED status, to toggle the light
unsigned long lastPeakTime = 0; //used for calculating peak
int currentPeak = 0;
int blinkCounter = 0;

void setup() {
  pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT
  pinMode(rfTransmitPin, OUTPUT);
  pinMode(knockSensor, INPUT);

  Serial.begin(9600);       // use the serial port for debugging
}

void loop() {
  // read the sensor and store it in the variable sensorReading:
  sensorReading = analogRead(knockSensor);
  if (sensorReading > currentPeak) {
    currentPeak = sensorReading;
  }

  // if the sensor reading is greater than the threshold:
  if (sensorReading >= threshold) {
    Serial.print(sensorReading);
    Serial.println(" Knock! ");

    while (blinkCounter <= 3)
    {
      Serial.println(blinkCounter);
      digitalWrite(rfTransmitPin, HIGH);     //Transmit a HIGH signal
      digitalWrite(ledPin, HIGH);            //Turn the LED on
      delay(500);                           //Wait 

      digitalWrite(rfTransmitPin, LOW);     //Transmit a LOW signal
      digitalWrite(ledPin, LOW);            //Turn the LED off
     
      delay(50);
      digitalWrite(ledPin, LOW);
      delay(50);
      blinkCounter++;
    }
    blinkCounter = 0;
    delay(50);
  }
  //DEBUG CODE THAT GETS WRITTEN TO SERIAL, NOT NECESSARY TO LEAVE IN
  if (millis() - lastPeakTime > 2000) {
    Serial.print("Peak value: ");
    Serial.println(currentPeak);
    lastPeakTime = millis();
    currentPeak = 0;
  }


}

Rx code

/*
  Target Sensor recieve module.
  ------------------------------------------------------------- */

#define rfReceivePin A0  //RF Receiver pin = Analog pin 0
#define ledPin 9        //Onboard LED = digital pin 9

unsigned int data = 0;   // variable used to store received data
const unsigned int upperThreshold = 70;  //upper threshold value
const unsigned int lowerThreshold = 50;  //lower threshold value

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  data = analogRead(rfReceivePin);  //listen for data on Analog pin 0

     if(data>upperThreshold){
     digitalWrite(ledPin, LOW);   //If a LOW signal is received, turn LED OFF
     Serial.println(data);
   }
   
   if(data<lowerThreshold){
     digitalWrite(ledPin, HIGH);   //If a HIGH signal is received, turn LED ON
     Serial.println(data);
   }
 }

I should also note that I have swapped both the rf rx unit and the rx arduino boards with no change.

What do the Serial.println statements show you when the LED goes on (that is, is the data greater/less than the threshold being tested)?

In which case it's doing what it's supposed to but not what you want! Let us know...

I jusat checked the serial monitor, and the values are a string of highs in the 740's followed by a string of 0's. Does the rx unit (I'm using the 433mhz variety), have to be connected to an analog pin, or can it be connected to a digital pin? I have an 11 second video of what its doing as well as a pic of the breadboard configuration but cant upload either one.

The desired output is to have the LED LOW until a signal is received at which time the LED should alternate between High and Low then return to Low when the signal goes away. The LED does in fact cycle High Low when the piezo is tapped on the Tx unit, but the "no signal Low" never happens. in other words the signal from the Tx unit does interrupt the LED but this is the opposite of what I'm trying to accomplish. Also with the RF Rx unit removed from the circuit the LED is constantly on.

Ok, so I’ve checked the provided references,(thanks to all that contributed), as well as this one,http://www.hackshed.co.uk/rf-communication-between-2-arduinos/.

This has become more than the “simple” project I thought I would be, Tx unit senses vibration via piezo, sends signal to Rx unit and LED flashes…

I have reconfigured my hardware setup connecting the Rx data pin to a digital pin 15,(originally connected to analog per an earlier tutorial I followed). I have also reconsidered the original code, and have come up with the following by combining the knock sensor code and the tx and rx codes from the hackshed article. I believe I’m close to having this right because the flickering LED is gone an about 30% of the time I get the desired response. I don’t know if the missed signals are due to corrupt data, or something else… The code I am using transmits a pincode and a number, in this case the pincode is 1 and data# is 5, as I understand it this should allow me to individually address or prevent cross talk between separate pairs if I want to use more than one set of sensor/receivers. I also read that the rx units need a "preamble " to get them ready to accept data, I do not know if the code I’m using has this or how to add it if not.

The components are currently breadboarded and I have added external antennas to the rf units.

Tx unit Piezo is connected to gnd and A0 with a 1Mohm resistor across the legs, 5v LED on pin 9 as a visual indicator for the tx unit, 433 Mhz Tx module gnd-gnd,vcc-vcc, and data-pin 4.

Rx unit has a 5v LED array connected to gnd and pin 9 and the 433 Mhz Rx module is connected gnd-gnd, vcc-vcc, and data-pin 15.

The Arduino module is as follows Mini Leonardo Pro Micro ATmega32U4 5V/16MHz Module
and the 433 Mhz pair are as below (copied from the Ebay description)
radio_pair_wm.jpg

Receiver:

Product Model:MX-05V
Operating voltage:DC5V
Quiescent Current:4MA
Receiving frequency:433MHz
Receiver sensitivity: -105 dB
Size:30 * 14 * 7mm
External antenna:32CM single core wire, wound into a spiral

Transmitter:

Product Model:MX-RM-05+
Range : 20-200 meters (different voltages can give different results)
Operating voltage:3.5-12V
Dimensions:19 * 19mm
Operating mode:AM
Transfer rate:4 kB / S
Transmitting power:10mW
Transmitting frequency:433MHz
An external antenna:25cm ordinary multi-core or single-core line
Pin Out from left to right: (DATA, VCC, GND)

Tx code

/*
  Target Sensor Transmit module.
  ------------------------------------------------------------- */
#include <VirtualWire.h>
const int ledPin = 9;      // led connected to digital pin 9
const int knockSensor = A0; // the piezo is connected to analog pin 0


const int threshold = 50;  // threshold value to decide when the detected sound is a knock or not

int sensorReading = 0;      // variable to store the value read from the sensor pin
int ledState = LOW;         // variable used to store the last LED status, to toggle the light
unsigned long lastPeakTime = 0; //used for calculating peak
int currentPeak = 0;



void setup() {
  pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT

  pinMode(knockSensor, INPUT);

  Serial.begin(9600);       // use the serial port for debuggin
  vw_set_ptt_inverted(true);
  vw_setup(1200);
  vw_set_tx_pin(4);
}

void loop() {
  // read the sensor and store it in the variable sensorReading:
  sensorReading = analogRead(knockSensor);
  if (sensorReading > currentPeak) {
    currentPeak = sensorReading;
  }

  // if the sensor reading is greater than the threshold:
  if (sensorReading >= threshold) {
    Serial.print(sensorReading);
    Serial.println(" Knock! ");
    sendMessage("1", "5");

    digitalWrite(ledPin, HIGH);            //Turn the LED on
    delay(150);                           //Wait
    digitalWrite(ledPin, LOW);            //Turn the LED off
    delay(150);
    digitalWrite(ledPin, HIGH);            //Turn the LED on
    delay(150);                           //Wait
    digitalWrite(ledPin, LOW);            //Turn the LED off
    delay(150);
    digitalWrite(ledPin, HIGH);            //Turn the LED on
    delay(150);                           //Wait
    digitalWrite(ledPin, LOW);            //Turn the LED off
    delay(150);
    digitalWrite(ledPin, HIGH);            //Turn the LED on
    delay(150);                           //Wait
    digitalWrite(ledPin, LOW);            //Turn the LED off



  }
}

void sendMessage(char* pinCode, char *data) {
  if (strlen(data) > 0) {
    //double startTime = millis();
    //Serial.println("Sending...");
    int msgSize = (strlen(data) + strlen(pinCode) + 1);
    char packetData[msgSize];
    strcat(packetData, pinCode);
    strcat(packetData, ".");
    strcat(packetData, data);

    //Serial.println("Debugging ");
    //Serial.print("Sending Command: ");
    //Serial.print(data);
    //Serial.print(" with Pin Code: ");
    //Serial.print(pinCode);
    //Serial.print("\n");

    vw_send((uint8_t *)packetData, msgSize);
    vw_wait_tx();

    //double endTime = millis();
    //double timeTaken = (endTime - startTime);
    //Serial.print("Time Taken: ");
    //Serial.print(timeTaken);
    //Serial.print(" ms\n");
  }
}

Rx Code

#include <VirtualWire.h>
#include <string.h>
const int ledPin = 9;      // led connected to digital pin 9
int ledState = LOW;         // variable used to store the last LED status, to toggle the light
byte message[VW_MAX_MESSAGE_LEN];
byte messageLength = VW_MAX_MESSAGE_LEN;

void setup() {
  pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT
  Serial.begin(9600);
  vw_set_ptt_inverted(true);
  vw_setup(1200);
  vw_set_rx_pin(15);
  vw_rx_start();
}

void loop() {
  if (vw_get_message(message, &messageLength)) {
    int command = processResponse((char*)message, 1); //Byte Array Response and Pin Code.
    if (command) {
      Serial.print("Received Command: ");
      Serial.print(command);
      Serial.print("\n");
      digitalWrite(ledPin, HIGH);            //Turn the LED on
      delay(150);                           //Wait
      digitalWrite(ledPin, LOW);            //Turn the LED off
      delay(150);
      digitalWrite(ledPin, HIGH);            //Turn the LED on
      delay(150);                           //Wait
      digitalWrite(ledPin, LOW);            //Turn the LED off
      delay(150);
      digitalWrite(ledPin, HIGH);            //Turn the LED on
      delay(150);                           //Wait
      digitalWrite(ledPin, LOW);            //Turn the LED off
      delay(150);
      digitalWrite(ledPin, HIGH);            //Turn the LED on
      delay(150);                           //Wait
      digitalWrite(ledPin, LOW);            //Turn the LED off

    }
  }
}

int processResponse(char* message, int pinCode) {
  char *p = message;
  char *buf;
  int o = 0;
  int pin;
  int command;

  while ((buf = strtok_r(p, ".", &p)) != NULL)  {
    if (o == 0) {
      pin = atoi(buf);
    } else {
      command = atoi(buf);
    }
    o++;
  }

  if (pinCode == pin && command > 0) {
    return command;
  } else {
    return 0;
  }
}