RF 433 Transmitter and Receiver with sensors and OLED displays

In this video I show you how to send data between 2 Arduino Nanos and use some OLED displays to show if something happened. I wanted to use a microphone as a triggering device, but my microphone circuit was not working as I wanted to. The main concept of this circuit is to see something remotely, but you can easily transform this idea into a for example remote controller.



Wiring diagram

RF433 transmitter (left) and receiver (right). The sound sensor show in the video is substituted by a potentiometer on the drawing. It emulates a signal level. The displays are i2C compatible OLED displays. They are connected to A4 (SDA) and A5 (SCL…

RF433 transmitter (left) and receiver (right). The sound sensor show in the video is substituted by a potentiometer on the drawing. It emulates a signal level. The displays are i2C compatible OLED displays. They are connected to A4 (SDA) and A5 (SCL) pins.



Arduino source code

Transmitter

#include <RH_ASK.h> //RadioHead Amplitude Shift Keying Library
 
#include <SPI.h> //SPI Library
#include <Wire.h> //Wire Library (I2C)
 
//ASCII-based OLED library
//Its huge advantage that it is _not_ graphical, so it is using much less memory
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
// 0X3C+SA0 - 0x3C or 0x3D
#define I2C_ADDRESS 0x3C //Address
#define RST_PIN -1 //For OLED with no reset pin
 
SSD1306AsciiAvrI2c display; //Instantiating a display
RH_ASK rf_driver; //Instatiating a rf_driver for the transmitter
 
int soundLevel = 0; //variable for the microphone's output
int triggerLevel = 0;
int AVGsoundLevel = 0;
int messageNumber = 0; //1 = triggered, 0 = reset (receiver will wait for a new trigger).
bool triggered = false; //we change this based on the status
 
//PINS
int microphonePin = A6;
int redLED = 5; // On, when triggered (Triggered)
int greenLED = 6; //on when not triggered (Waiting)
int calibratePin = 2; //to save the triggel level
 
void setup()
{
 
  //Initializing the display
  #if RST_PIN >= 0
  display.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
  #else // RST_PIN >= 0
  display.begin(&Adafruit128x64, I2C_ADDRESS);
  #endif // RST_PIN >= 0
  display.setFont(System5x7); //font type
  display.set1X(); //font size (small)
  display.clear();
  //-----------------------------------------------------    
  // Initialize ASK Object
  rf_driver.init();
  //-----------------------------------------------------
  //Pins. By default, green will be on.
  pinMode(calibratePin, INPUT_PULLUP); //use the internal pullup
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
 
  digitalWrite(redLED, LOW);
  digitalWrite(greenLED, HIGH);
 
  attachInterrupt(digitalPinToInterrupt(calibratePin), triggerSoundLevel, RISING); //L -> H, button for calibration
 
}
 
void loop()
{    
    PrintScreen();    //Print the info on the screen
   
    MeasureSound();   //Measure the sound
   
}
 
 
void PrintScreen()
{  
  display.clear();  //clear display
  display.setCursor(0, 0); //start in the 0 position  
  //----------------------------
  display.print("Level: ");  
  display.println(AVGsoundLevel);  
  display.println();
  //----------------------------
  display.print("Trigger level: ");  
  display.println(triggerLevel);
  //----------------------------
  display.println();
  display.print("Status: ");
  if(triggered == false)
  {
    //This gets printed if we do not cross the trigger value
    display.println("Waiting");
    messageNumber = 0; //sends a 0 to the receiver
    SendMessage(messageNumber);
    digitalWrite(redLED, LOW); //only green is on while waiting
    digitalWrite(greenLED, HIGH);
   
  }
  else
  { //triggered == true
    //This gets printed if we cross the trigger value
    display.println("Triggered");
    messageNumber = 1; //sends a 0 to the receiver
    SendMessage(messageNumber);
    digitalWrite(redLED, HIGH); //red is on when triggered and green is off
    digitalWrite(greenLED, LOW);    
  }
       
}
 
void MeasureSound()
{
  soundLevel = 0; //Reset it, before filling it up
  AVGsoundLevel = 0; //Reset it, before filling it up
 
  //Let's measure it for some time and create an average
  for(int i = 0; i < 10; i++)
  {
    soundLevel += analogRead(microphonePin);
    delay(200);
  }
  AVGsoundLevel = soundLevel / 10; //calculate average
 
  if(AVGsoundLevel < (triggerLevel-100)) //if there is less value, we flip the value of the variable
  {
    triggered = true; //set the bool to true
  }
  else
  {
    triggered = false; //set the bool to false
  }
 
}
 
void triggerSoundLevel()
{
  soundLevel = 0;   //Reset it, before filling it up
  triggerLevel = 0; //Reset
 
  for(int i = 0; i < 10; i++)
  {
    soundLevel += analogRead(microphonePin);
    delay(200);    
  }
    triggerLevel = soundLevel / 10;  //calculate average
   
    soundLevel = 0; //Reset it, again, otherwise, it goes to weird levels in the measure()    
   
}
 
void SendMessage(int messageNumber)
{
    rf_driver.send((uint8_t *)&messageNumber, sizeof(messageNumber)); //send the message through the RF module    
    rf_driver.waitPacketSent();  
}

Receiver

#include <RH_ASK.h>//RadioHead Amplitude Shift Keying Library
#include <SPI.h> // SPI Library
#include <Wire.h> //Wire Library (I2C)
 
RH_ASK rf_driver; //Instatiating a rf_driver for the receiver
 
//ASCII-based OLED library
//Its huge advantage that it is _not_ graphical, so it is using much less memory
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
#define I2C_ADDRESS 0x3C //Address
#define RST_PIN -1 //For OLED with no reset pin
 
SSD1306AsciiAvrI2c display;
 
 
// Set buffer to size of expected message
    uint8_t buf[24];
    uint8_t buflen = sizeof(buf);
 
    String receivedString; //String for long messages
 
//REC pin = D11
int redLED = 5; //on, when it is too loud
int greenLED = 6; //on when it is OK
 
 
void setup()
{
    // Initialize ASK Object
    rf_driver.init();
   
  #if RST_PIN >= 0
  display.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
    #else // RST_PIN >= 0
  display.begin(&Adafruit128x64, I2C_ADDRESS);
    #endif // RST_PIN >= 0
  // Call oled.setI2cClock(frequency) to change from the default frequency.
 
  display.setFont(System5x7);
  display.set1X();
  display.clear();
 
   //Managing the LEDs
   pinMode(redLED, OUTPUT);
   pinMode(greenLED, OUTPUT);
 
   digitalWrite(redLED, LOW);
   digitalWrite(greenLED, HIGH);
   //----------------------------
 
  //Serial.begin(9600);
  //Serial.println("Receiver started");
}
 
void loop()
{
   
    // Check if received packet is correct size
    if (rf_driver.recv(buf, &buflen))
    {    
 
      for (int i = 0; i < buflen-1; i++)
      {    
        receivedString += String(buf[i]); //building up a string from the received data            
      }
     
      PrintScreen(); //print to OLED  
      receivedString="";  //reset to zero, so we don't mix the messages
     
    }
   
}
 
void PrintScreen()
{
  display.clear();  
  display.setCursor(0, 0);
  display.println("Status: ");
  display.println();
 
  if(receivedString == "0")
  {
    display.println("Waiting...");
    digitalWrite(redLED, LOW);
    digitalWrite(greenLED, HIGH); //Only green is on, while we are waiting
  }
  if(receivedString == "1")
  {  
    display.println("Check device!");
    digitalWrite(redLED, HIGH); //Red goes on, when the trigger level is crossed on the transmitter side
    digitalWrite(greenLED, LOW);
  }
 
 
}

Previous
Previous

Direct control of a stepper motor using a rotary encoder and the accelstepper library

Next
Next

Brief introduction of strain gauges - Part 1