Practical use of ultrasonic Sensor with ATMEGA328P and Raspberry PI

Practical use of Ultrasonic Sensor SR04 with ATMEGA328P and Raspberry PI

Introduction

I2C is a two-wire bus that is designed to be simple, reliable, and energy-efficient. It is often used to connect microcontrollers, sensors, and other peripherals. I2C is also widely used for communication between microcontrollers and external memory.

In this article, we present an alternative to directly using the Raspberry PI GPio to control external devices. I2C makes it possible to consume external data using this communication method. We use an Arduino UNO as a slave I2C device, controlling the HC-SR04 Ultrasonic Sensor, and a Raspberry PI B+ as a master I2C device, consuming the Sensor Data. In addition, the code for both the ATMEGA328P and Raspberry PI B+ has been included.

Connection Diagram

Default Image Title

Raspberry as I2C Master Code

#!/usr/bin/env python

from smbus2 import SMBus, i2c_msg
import time
import struct

# bus = smbus.SMBus(1)

address = 0x0A

def read_float_from_arduino(address):
   with SMBus(1) as bus:
       b = []
       for _ in range(4):
           b.append(bus.read_byte(address))
       f = struct.unpack('f', bytearray(b))
       # print([hex(n) for n in b])
       # print("{0:4f}".format(f[0]))
       return f[0]


if __name__ == '__main__':
   bus = SMBus(1)
   try:
       while True:
           float_value = read_float_from_arduino(address)
           print("{0:3f} cms".format(float_value))
           time.sleep(0.25)
   except KeyboardInterrupt:
       pass

ATMEGA328P as I2C Slave Code


#include <Wire.h>

#define I2C_SLAVE_ADDRESS 10 // I2C Id Address
#define TRIGGER 2    //Digital Pin for Sensor Trigger
#define ECHO   3    //Digital Pin for Sensor Echo
#define LEDPIN 13   //General Purpose LED

union FloatUnion {
   float number;
   uint8_t bytes[4];
} dataToSend;

int byteCount = 0;
int sampleSize = 5;


void setup() {
 Wire.begin(I2C_SLAVE_ADDRESS);
 Serial.begin(9600);
 delay(1000);
 
 // Setup HC-SR04 Sensor
 pinMode(TRIGGER, OUTPUT);   //Setup TRIGGER as output
 pinMode(ECHO, INPUT);       //Setup ECHO as input
 digitalWrite(TRIGGER, LOW); //Init TRIGGER with 0
 
 // Setup Send and Receive I2C Interrupt Methods  
 Wire.onRequest(requestEvent);
 Wire.onReceive(receiveEvent);

 Serial.println("--------- Arduino Configure as Slave on I2C ----------");
 dataToSend.number = retrieveAvgMeasureSample(sampleSize);
}


void loop() {
 //Serial.println(retrieveAvgMeasureSample(3));
 dataToSend.number = retrieveAvgMeasureSample(sampleSize);
 delay(10);  
}

/*
*
*/
float retrieveSingleMeasure(){
 long  echoTime;     //Time length for echo retrieving
 float distance;     //Distance in cms
 // Send 10us duration pulse
 digitalWrite(TRIGGER, HIGH);
 delayMicroseconds(10);          //Enviamos un pulso de 10us
 digitalWrite(TRIGGER, LOW);

 echoTime = pulseIn(ECHO, HIGH); //Retrive the echo pulse width
 distance = echoTime/59;         //Time scaling for a particular distance in cms
 
 delay(100);  //Pause for 100ms
 return  distance;
}


/**
*
*/
float retrieveAvgMeasureSample(int sampleSize) {
 float currentSample = 0;
 for(int nSample = 0; nSample < sampleSize; nSample++)
    currentSample += retrieveSingleMeasure();
 return currentSample/sampleSize;
}


/**
*
*/
void requestEvent(){    
 for(int i = 0; i < 4; i++){
   Serial.print(dataToSend.bytes[i], HEX);
   Serial.print(" ");
}
 Serial.println("");
 //
 Wire.write(dataToSend.bytes[byteCount++]);
 if (byteCount == 4) byteCount=0;
}


/**
*
*/
void receiveEvent(int numBytes) {
 for(int i = 0; i < numBytes; i++){
   byte byteReceived = Wire.read();
   Serial.print(byteReceived, HEX);
   Serial.print(" ");
}

 Serial.println("");
}


Comments