New file |
| | |
| | | /* |
| | | ____ _____ _ _ |
| | | | __ )| ____| | / \ |
| | | | _ \| _| | | / _ \ |
| | | | |_) | |___| |___ / ___ \ |
| | | |____/|_____|_____/_/ \_\ |
| | | http://bela.io |
| | | */ |
| | | /** |
| | | \example Sensors/ultrasonic-distance-sensor/render.cpp |
| | | |
| | | Measuring distances with ultrasonic sensors |
| | | --------------------------- |
| | | |
| | | Ultrasonic sensors can detect distances to a high degree of accuracy, even |
| | | in many conditions where infrared sensors would not be suitable (e.g.: when natural |
| | | light is a problem. |
| | | For this example we used the [HC-SR04](https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf). |
| | | |
| | | After it receives a short pulse (> 10us) at its TRIGGER input, the module outputs from the |
| | | ECHO output a pulse whose length is proportional to the distance of the object that is in |
| | | front of the sensor. When a trigger is received the module emits an ultrasonic wave |
| | | from its emitter and then receives the signal back in its receiver, measuring the time |
| | | difference between the two. |
| | | |
| | | According to the datasheet of this sensor, the following relation stands: |
| | | time[us] / 58 = distance[cm] |
| | | The dataseheet recommends a minimum interval of 60ms between triggers, in order to be able to |
| | | read the result appropriately. |
| | | |
| | | Bela sends out the TRIGGER event every 2646 samples(60ms) and then waits for a pulse to come |
| | | appear on the ECHO pin. The `PulseIn` class is used here to monitor a digital pin for an HIGH |
| | | pulse and once the pulse termiantes, it returnes the duration ( in samples ) of the pulse. |
| | | |
| | | The module requires a 5V power supply and its digital inputs and outputs are low at 0V and |
| | | HIGH at 5V. Check the pin diagram in the IDE to see where to find the pins you need. |
| | | It is important that the 5V ECHO output from the module *is not* connected |
| | | straight to Bela's digital inputs, as that would most likely kill the Bela board |
| | | (digital I/Os are 3.3V tolerant). You will need to use a passive resistor divider from the |
| | | HC-SR04's ECHO output to scale down the voltage before connecting it to the digital input |
| | | on `gEchoDigitalInPin`. |
| | | |
| | | On the scope you should see the pulses coming in from the trigger and the distance. The closer |
| | | the object, the shorter the pulses. Make sure you set the trigger to "channel 1" (the pulse) and |
| | | you set the horizontal zoom appropriately. |
| | | */ |
| | | |
| | | #include <Bela.h> |
| | | #include <stdlib.h> |
| | | #include <libraries/Scope/Scope.h> |
| | | #include <libraries/PulseIn/PulseIn.h> |
| | | |
| | | PulseIn pulseIn; |
| | | Scope scope; |
| | | int gTriggerInterval = 2646; // how often to send out a trigger. 2646 samples are 60ms |
| | | int gMinPulseLength = 7; //to avoid spurious readings |
| | | float gRescale = 58; // taken from the datasheet |
| | | unsigned int gTrigDigitalOutPin = 7; //channel to be connected to the module's TRIGGER pin - check the pin diagram in the IDE |
| | | unsigned int gEchoDigitalInPin = 7; //channel to be connected to the modules's ECHO pin via resistor divider. Check the pin diagram in the IDE |
| | | int gTriggerCount = 0; |
| | | int gPrintfCount = 0; |
| | | |
| | | bool setup(BelaContext *context, void *userData) |
| | | { |
| | | // Set the mode of digital pins |
| | | // pinMode(context, 0, gTrigDigitalOutPin, OUTPUT); // writing to TRIGGER pin |
| | | // pinMode(context, 0, gEchoDigitalInPin, INPUT); // reading from ECHO pin |
| | | pulseIn.setup(context, gEchoDigitalInPin, HIGH); //detect HIGH pulses on the ECHO pin |
| | | scope.setup(2, context->digitalSampleRate); |
| | | return true; |
| | | } |
| | | |
| | | void render(BelaContext *context, void *userData) |
| | | { |
| | | for(unsigned int n = 0; n < context->digitalFrames; ++n){ |
| | | gTriggerCount++; |
| | | bool state; |
| | | if(gTriggerCount == gTriggerInterval){ |
| | | pinMode(context, 0, gTrigDigitalOutPin, OUTPUT); // writing to TRIGGER pin |
| | | state = LOW; |
| | | digitalWriteOnce(context, n, gTrigDigitalOutPin, state); |
| | | } else if (gTriggerCount == gTriggerInterval+1) { |
| | | pinMode(context, 0, gTrigDigitalOutPin, OUTPUT); // writing to TRIGGER pin |
| | | state = HIGH; |
| | | digitalWriteOnce(context, n, gTrigDigitalOutPin, state); |
| | | } else if (gTriggerCount == gTriggerInterval+2) { |
| | | gTriggerCount = 0; |
| | | state = LOW; |
| | | digitalWriteOnce(context, n, gTrigDigitalOutPin, state); |
| | | } else { |
| | | pinMode(context, 0, gTrigDigitalOutPin, INPUT); // writing to TRIGGER pin |
| | | } |
| | | |
| | | auto dRead = digitalRead(context, n, gEchoDigitalInPin); |
| | | int pulseLength = pulseIn.hasPulsed(context, n); // will return the pulse duration(in samples) if a pulse just ended |
| | | |
| | | float duration = 1e6 * pulseLength / context->digitalSampleRate; // pulse duration in microseconds |
| | | |
| | | static float distance = 0; |
| | | if(pulseLength >= gMinPulseLength){ |
| | | // rescaling according to the datasheet |
| | | distance = duration / gRescale; |
| | | } |
| | | static int count = 0; |
| | | if(count > 5000){ // we do not want to print the value every time we read it |
| | | rt_printf("pulseLength: %d, distance: %fcm\n", pulseLength, distance); |
| | | count = 0; |
| | | } |
| | | ++count; |
| | | // Logging to the scope the pulse inputs (gEchoDigitalInPin) and the distance |
| | | scope.log(dRead * 0.5, distance/100); |
| | | } |
| | | } |
| | | |
| | | void cleanup(BelaContext *context, void *userData) |
| | | { |
| | | } |