Speed measurement with arduino and ultrasonic hc-sr04 sensor? - arduino

i want made speed detection "device" using with Arduino and two ultrasonic hc-sr04 like this link. but I want to make it with ultrasonic instead by LDR.
from that link. how lasers and ldr work, like this
The resistors are used as pull-down resistors and I wired the sensors and put them in a case, to avoid them detecting surrounding light. For each case, a hole was drilled so that the laser beam can light the sensor while the ambient light does not affect the sensor.
The working principle is easy: an object that passes by will "cut" the laser beams, this means the LDR sensor will detect this sudden drop of light intensity. First I defined a threshold value under which the sensor is considered triggered, once the value is under threshold for the first sensor then Arduino waits for the second one to be triggered. During this waiting time it counts the elapsed time between the two events. When the second beam is interrupted, the timer stops and now is just simple math. The distance between the 2 sensors is known, the time between the two events is known, and speed can be computed as speed = distance/time.
Below the Arduino code:
/*
by Claudiu Cristian
*/
unsigned long time1;
int photocellPin_1 = 0; // 1st sensor is connected to a0
int photocellReading_1; // the analog reading from the analog port
int photocellPin_2 = 1; // 2nd sensor is connected to a1
int photocellReading_2; // the analog reading from the analog port
int threshold = 700; //value below sensors are trigerd
float Speed; // declaration of Speed variable
float timing;
unsigned long int calcTimeout = 0; // initialisation of timeout variable
void setup(void) {
// We'll send debugging information via the Serial monitor
Serial.begin(9600);
}
void loop(void) {
photocellReading_1 = analogRead(photocellPin_1); //read out values for sensor 1
photocellReading_2 = analogRead(photocellPin_2); //read out values for sensor 2
// if reading of first sensor is smaller than threshold starts time count and moves to calculation function
if (photocellReading_1 < threshold) {
time1 = millis();
startCalculation();
}
}
// calculation function
void startCalculation() {
calcTimeout = millis(); // asign time to timeout variable
//we wait for trigger of sensor 2 to start calculation - otherwise timeout
while (!(photocellReading_2 < threshold)) {
photocellReading_2 = analogRead(photocellPin_2);
if (millis() - calcTimeout > 5000) return;
}
timing = ((float) millis() - (float) time1) / 1000.0; //computes time in seconds
Speed = 0.115 / timing; //speed in m/s given a separation distance of 11.5 cm
delay(100);
Serial.print(Speed);
Serial.print("\n");
}
how to implement the code with ultrasonic HC-SR04 sensors?
the coding is problem for me. hopefully someone can help me...... :(
Please excuse my poor English !

There are already lots of examples on the internet, so if all you want to do is copy, google arduino sr04
But if you want to know how to do it...
The sr04 has 4 pins, vin, gnd, trigger, and echo.
Connect vin and ground to +5 and gnd
Connect trigger to a digital output pin
Connect echo to a digital input pin
Trigger by going low for 2 microseconds (us) and then high for 10 us then low again
Then get the results with a pulseIn from the echo pin
Read the data sheet for more information

Related

Arduino Interrupt getting triggered more than once - Working with Hall Sensor for RPM

I am working with an hall sensor for counting the RPM of my wheel. I am using following sensor :
My code as follows :
int hall_pin = 3; // digital pin
float hall_threshold = 5.0;
float count = 0;
void setup() {
pinMode(hall_pin,INPUT);// put your setup code here, to run once:
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(hall_pin),hall_ISR,RISING);
}
void loop() {
count = 0.0;
float start = micros();
while(1){
if(count >= hall_threshold){
break;
}
}
float end_time = micros();
float time_passed = (end_time - start)/1000000.0; // in seconds
float rpm = (count/time_passed)*60.0;
Serial.println(rpm);
delay(10000);
}
void hall_ISR()
{
count+=1.0;
}
I am using digital pin 3 to read from sensor and count the number of times it detects magnetic field using interrupt. Since the sensor outputs 1 on detecting, I have used a RISING interrupt. Once the count is greater than 5 then the control comes out of the infinite loop and calculates the RPM. The problem is this interrupt is getting triggered multiple times. I have tried using detachInterrupt(hall_pin) but it is not working. I also tried to decrease the sensitivity of hall sensor using the trimmer provided.
I am sure the problem is not with the sensor, it is with the interrupt, I guess. Where am I going wrong?
Any help is very much appreciated!
Thank you.

Arduino interrupts

I am working on a smart greenhouse project using an ESP32 as a microcontroller.
Data comes from a DHT22 temperature and humidity sensor and a soil moisture sensor. Those two tend to use delay() functions to read, because they need some time to warm up.
Example:
void loop() {
// Wait a few seconds between measurements.
delay(2000);
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
}
I am planning on posting this data on a web interface, which would have manual controls available too.
Since I am using delays, if I press the button on the website, first the delay executes, then the button press, so it's not instant. What could I do to fix that?
Don't use delay(). I'm not clear on exactly what you're trying to do here or how you're trying to handle the button, but in general you're better off doing something like this:
#define SENSOR_UPDATE_WARMUP 2000
#define SENSOR_UPDATE_INTERVAL 1000
void loop() {
static unsigned long next_sensor_update = SENSOR_UPDATE_WARMUP;
if(millis() > next_sensor_update) {
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
next_sensor_update = millis() + SENSOR_UPDATE_INTERVAL;
}
}
This allows you to other processing in loop() while still having the warmup time and only updating the sensor readings periodically (adjust SENSOR_UPDATE_INTERVAL to the number of milliseconds between updates).
If you need to have other delays for other devices just repeat the pattern of having a static variable that tracks the timing for those devices.
Even simpler, you could just put the two second delay at the end of setup() rather than inside loop(), but I suspect you're not going to want to update the sensor values constantly, so you'll want to structure your program similarly to the code above.

LM35 decreases when near heat

My LM35 connected to arduino decreases temperature value in celsius when near heat and increases value when far from heat. Could any one help or know why it's working other way round.
void setup() {
// put your setup code here, to run once:
//Start the serial connection with the computer
//to view the result open the serial monitor
// 9600 is the “baud rate”, or communications speed.
Serial.begin(9600);
}
void loop() {
delay(2000);
float tempValue = analogRead(A2);
// converting that reading to voltage
float tempVoltage = (tempValue/1024.0)*5.0;
float tempDegrees = (tempVoltage - 0.5) * 100.0 ;
//Multiplying tempDegrees by -1 to make it positive
tempDegrees =(tempDegrees * -1);
Serial.println("............................................");
Serial.println("Degrees");
Serial.println(tempDegrees);
delay(2000);
}
just randomly came accross your question. and it has been 6 years since I touched an LM35 :d
but I think you have a problem in that -0.5 thing. I did not really get that!
LM35's function as far as I remember was :
T = V/ 10mV
you might want to check the datasheet but I'm pretty positive this is the equation. when you get the voltage from ADC you have to put it in this equation and get the result.
be careful : you have to also attribute for the temperature error as well as ADC noise if temperature precision is important for you.
If you are using a 5 volts power supply to your arduino:
5 Volts in the Arduino are directly converted to 1023 in the output of the ADC
ADC_Outpput * 5000 / 1024, where 5000 is coming from 5volts as millivolts, 1024 is the 10 bist resolution
LM35 resolution is linearly generated with a rate of + 10-mV/°C
so the analogVolt = ADC_Outpput * 5000 / 1024
FinalTemperature = (analogVolt - 500) / 10

Arduino Mini Pro 3.3V does not use 1.1V internal reference for ADC

Using the Arduino Mini Pro 3.3V I just stumbled over a problem when switching between the "INTERNAL" and "DEFAULT" voltage reference for the ADC.
I want to measure the output of a voltage divider [GND - 110kOhm - A2 - 500kOhm - VCC] for calculating VCC. VCC has been measured as 3.3V. It is provided by a voltage regulator.
In the loop I firstly measure the voltage divider output with the internal reference and afterwards with the default voltage reference.
I saw code examples where people recommend to wait some milliseconds before reading the next value and the (analogReference() documentation) recommends to ignore the first readings after calling analogReference(). I follow these guidlines.
I'll provide a minimum example sketch:
// the setup function runs once when you press reset or power the board
void setup()
{
pinMode(A2, INPUT); // ADC pin
Serial.begin(9600);
Serial.println("----------------");
}
void burn8Readings(int pin)
{
for (int i = 0; i < 8; i++)
{
analogRead(pin);
}
}
// the loop function runs over and over again forever
void loop()
{
uint16_t nResult1, nResult2;
analogReference(INTERNAL); // set the ADC reference to 1.1V
delay(10); // idle some time
burn8Readings(A2); // make 8 readings but don't use them to ensure good reading after ADC reference change
nResult1 = analogRead(A2); // read actual value
analogReference(DEFAULT); // set the ADC reference back to internal for other measurements
delay(10); // idle again
burn8Readings(A2); // make 8 readings but don't use them to ensure good reading after ADC reference change
nResult2 = analogRead(A2); // do other measurements
// print result to serial interface..
Serial.print("1: ");
Serial.print(nResult1);
Serial.print(" - 2: ");
Serial.println(nResult2);
delay(2000);
}
The first pair of ADC results seems correct (553 / 184), but in the following iterations the first value is faulty without changing the actual voltage on the ADC pin. (240 / 183)
The ADC result of the DEFAULT reference is always fine.
For a 2.56V reference the value of 240 would be feasible. I know that some ATmegas use a 2.56V reference voltage, but the ATmega328 should have 1.1V only. Strangely the (ATmega328/P datasheet) mentions a 2.56V reference in an ADC example in chapter 28.7, so I'm confused.
Is there a possibility there is a 2.56V ADC reference in a certain ATmega328p version?
It turns out the similarity to the 2.56V was a coincidence and probably an error in the datasheet (or in my understanding).
The problem was that after the analogReference(INTERNAL) call the ADC value has to be read immediately! Not after some milliseconds as I did it. (Source)
Still it is important to also wait some milliseconds after doing the dummy readout. For me one readout and delay(5) was just enough, but I guess that depends on the charge left in the capacitor of the ADC: So I'd recommend higher delays.
The correct sequence is:
analogReference(INTERNAL); // set the ADC reference to 1.1V
burn8Readings(A2); // make 8 readings but don't use them
delay(10); // idle some time
nResult1 = analogRead(A2); // read actual value
and
analogReference(DEFAULT); // set the ADC reference back to internal
burn8Readings(A2); // make 8 readings but don't use them
delay(10); // idle again
nResult2 = analogRead(A2); // read actual value
Changing the reference back to DEFAULT seems to be less prone...but at least one readout still was necessary for precise results.
I hope no one has to spend time on this one anymore...

Using arduino analog inputs

I am creating my first Arduino program on the UNO r3. I have played with the Arduino Uno before just with petty example programs, etc. I am using two analog inputs to sense distance using 2 laser sensors with 0-5vdc scaling. These two inputs are 0-5vdc and I have ensured common grounding throughout. The two sensors are named left and right and are input to A0 and A1 respectively. I also have a differential POT which uses a 10K ohm POT wiper voltage as an input on A2. The theory of the program is to take the absolute value of the difference in input voltages between the left and right lasers then determine if the result is greater than or equal to the voltage on pin A2 from the POT wiper. Based on the resulting math, turn on or off a relay interposed to pin D13 via a transistor driver circuit.
The PROBLEM: I cannot achieve accurate changes in voltage on the scale (0-1023) on pins A0, A1, or A2. I have utilized the serial monitor to diagnose this problem. Not sure what the problem is, any help would be great. Also, I cannot achieve a 0 value on any of the above analog pins, even the POT wiper!!!
Here's my code:
const int lf_dist = A0; //names A0
const int rt_dist = A1; //names A1
const int differential = A2; //names A2
const int relay = 13; // select the pin for the relay coil
unsigned int left = 0; // variable to store the value coming from the left sensor
unsigned int right = 0; // variable to store the value coming from the right sensor
unsigned int diff = 0; // variable to store the value coming from the differential POT for maximum distance differential
unsigned int offset = 0; // variable that stores the value between the two laser sensors
void setup() {
Serial.begin(9600);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(relay, OUTPUT); // declare the relay pin as an OUTPUT:
analogReference(DEFAULT);
}
void loop()
{
unsigned int left = 0; // variable to store the value coming from the left sensor
unsigned int right = 0; // variable to store the value coming from the right sensor
unsigned int diff = 0; // variable to store the value coming from the differential POT for maximum distance differential
unsigned int offset = 0; // variable that stores the value between the two laser sensors
left = analogRead(A0); // read the value from the left laser
delay(5);
right = analogRead(A1); // read the value from the right sensor
delay(5);
diff = analogRead(A2); // read the value from the differential POT
delay(5);
offset = abs(left - right);
if(offset >= diff) // does math to check if left and right distances are greater than the value clocked in by the differential POT
{
digitalWrite(relay, LOW); // turns off the relay, opens the stop circuit, and turns on the yellow light
}
else
{
digitalWrite(relay, HIGH); // turns on the relay if all is good, and that keeps the machine running
}
Serial.print("\n left = " );
Serial.print(left);
Serial.print("\n right = " );
Serial.print(right);
Serial.print("\n differential = " );
Serial.print(diff);
delay(1000);
}
afaict, this should really be due to the floating pins surrounding the measuring pins, having erratic values, hence perturbating your measures. You should look at your values using arduinoscope, which will show you the interfering effects of the other floating pins on your measuring pins.
The easy workaround for this is to ground all analogical input pins you're not using, and put as much space as you can between both your inputs, so they don't interfere with each other.
I realize this thread is somewhat old not, but perhaps this will help someone. If you power the Arduino with only 5V, as you say you did with a regulator, you will get very erratic behavior, particularly from the analog pins. This is because you will start to brown out the internal voltage regulators that provide the AREF, 3.3, and 5.0 outputs. I've tested this for a robotics project I'm working on, and right around 6.5 volts, everything begins to go wrong. I suppose if you always provided 5.0 input voltage you could compensate for this effect, but in my case I used a LiPo battery that could range from 8.4 volts down to 6.0 volts, and everything goes crazy at 6.5 volts.
The minimum current that arduino sinks in during the sampling from potentiometer should not disturb the actual open input volts at the wiper.
Initialize the pins in pull up mode to avoid garbage values or 'floating' pins or use your own pull down/up resistors at the pins :)

Resources