Creating library for ultrasonic sensor hc-sr04

I’m trying to make this sensor work. I’m translating the library from arduino library

I would like to know what is the equivalent of pulseIn() from arduino in Viper?

If I have undderstood correctly I need to know for how much time the echo port of the sensor stays high.
Original arduino code:

//HC RS04 Sensore ultrasuoni
int triggerPort = ``7``;
int echoPort = ``8``;
 
void setup() {
 
pinMode( triggerPort, OUTPUT );
pinMode( echoPort, INPUT );
Serial.begin( ``9600 );
Serial.println( ``"Sensore ultrasuoni: "``);
 
}
 
void loop() {
//porta bassa l'uscita del trigger
digitalWrite( triggerPort, LOW );
 
//invia un impulso di 10microsec su trigger
digitalWrite( triggerPort, HIGH );
delayMicroseconds( ``10 );
digitalWrite( triggerPort, LOW );
 
long duration = pulseIn( echoPort, HIGH );
 
long r = ``0.034 * duration / ``2``;
 
Serial.print( ``"durata: " );
Serial.print( duration );
Serial.print( ``" , " );
Serial.print( ``"distanza: " );
 
//dopo 38ms è fuori dalla portata del sensore
if``( duration > ``38000 ) Serial.println( ``"fuori portata"``);
else { Serial.print( r ); Serial.println( ``"cm" );}
 
//aspetta 1.5 secondi
delay( ``1500 );
}

My Viper code:
import streams
import timers

global elapsed

streams.serial()

triggerPort = D1
echoPort = D2

pinMode(triggerPort, OUTPUT)
pinMode(echoPort, INPUT)

t = timers.timer()
try:
while True:
sleep(5000)
print(“start”)
digitalWrite(triggerPort,LOW)
sleep(2)
digitalWrite(triggerPort,HIGH)
sleep(10)
digitalWrite(triggerPort,LOW)
t.start()

here i should save the elapsed time with t.get() while the echo port was HIGH

except Exception as e1:
print(e1)

<span><br><br></span>

Hi,
looking at the HC-SR05 datasheet i found:

You can
calculate the range through the time interval between sending trigger signal and
receiving echo signal. Formula: uS / 58 = centimeters 
from Arduino Pulsein ref:
pulseIn()
Description
Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds or 0 if no complete pulse was received within the timeout.

Syntax
pulseIn(pin, value) 
pulseIn(pin, value, timeout)

in Viper you can use the ICU http://doc.viperize.it/core.viper.stdlib/r0.3.2/icu.html

your code should become:

import streams
import icu

streams.serial()

triggerPort = D1
echoPort = D2.ICU

pinMode(triggerPort, OUTPUT)
pinMode(echoPort, INPUT)

distance=0

try:
while True:
sleep(5000)
print(“start”)
digitalWrite(triggerPort,LOW)
sleep(2)
digitalWrite(triggerPort,HIGH)
sleep(10)
digitalWrite(triggerPort,LOW)
x = icu.capture(echoPort,LOW_TO_HIGH,1,1000,MICROS)
centimeters=x[0]/58
print(“centimeters”,centimeters)

except Exception as e1:
print(e1)

<p>it compiles but i don't have the sensor for testing the behaviour.</p><p>let me know if it works&nbsp;</p><p><span class="vanilla-mention-@">@LorenzoRizzello have you worked to something similar for the Groove sensors? is it the same? do you have to code?</span></p>

It’s not working.
I got and index error in the line after the ICU capture. "centimeters=x[0]/58"
In this line

x = icu.capture(echoPort,LOW_TO_HIGH,1,1000,MICROS)
Is&nbsp;<em>time_window=1000&nbsp;</em><span>the maximum time before suspending the ICU caputure if there wasn't any change in the state of the digitial pin (low/high) ?<br><br>The <a rel="nofollow" target="_blank" href="http://www.micropik.com/PDF/HCSR04.pdf">sr04 datasheet</a>&nbsp;refers to microseconds:<br><br></span><blockquote class="Quote"><span>(1) Using IO trigger for at least 10us high level signal,
<br>(2) The Module automatically sends eight 40 kHz and detect whether there is a
pulse signal back.
<br>(3) IF the signal back, through high level , time of high output IO duration is
the time from sending ultrasonic to returning.
Test distance = (high level time×velocity of sound (340M/S) / 2</span>&nbsp;<br><br></blockquote>So I think I should change the sleep(10) in sleep(10, time_unit=MICROS)<br>But if I do this i get a name error during the execution from try/except.<br><br>

i couldn’t test the code, print x and see how long it is… it could be null so you will have the index error.

you can change the timeout to the time you prefer, i just set 10000 as an example

for sleep micros try: 

sleep(10, MICROS)
another possibility for generating time constrained pulses is to use the PWM signal generator on the trigger port sending only one pulse of 10 MICROS.
pwm.write(triggerPort, 10, 10, MICROS, 1)
details on pwm here http://doc.viperize.it/core.viper.stdlib/r0.3.2/pwm.html 

Great it’s working!

I changed this line:

x = icu.capture(echoPort,LOW_TO_HIGH,1,60,MILLIS)
<br>

The datasheet says:<br><blockquote class="Quote">Formula: uS / 58 = centimeters or uS / 148 =inch; or: the
range = high level time * velocity (340M/S) / 2; we suggest to use over 60ms
measurement cycle, in order to prevent trigger signal to the echo signal.&nbsp;<br></blockquote>Was 60ms referring to that parameters of the ICU capture?<br><br>1000 micros was too low I think.<br>Thank you @floyd

60ms is a suggestion on the maximum sampling speed. but you have a sleep of 5000ms on top of the while so no problem.

the ICU configured as you reported timeouts after 60ms returning none if no “rise” on the pin is detected
D.

Great work :slight_smile:

It’s time to clean up and publish your library for the community!

Giacomo said:
Great work :)

It's time to clean up and publish your library for the community!
I tried doing it but the library isn't saved online (i get an error at compile time in the import line) it says that the just created library doesn't exist. 
If I create a local library it works.
Do I have to do something to upload my library? I already synched the cloud.


As you can read from the image the library path is sr04.sr04: is it normal the double "sr04.sr04"?I only wrote it once in the library creation window.

Can someone suggest a string manipulation to enable a user to write

distance =pippolibrary.getDistancesr04(D1,D2)

instead of

distance =pippolibrary.getDistancesr04(D1,D2.ICU) ?


Can someone suggest a string manipulation to enable a user to write

distance =pippolibrary.getDistancesr04(D1,D2)

instead of

distance =pippolibrary.getDistancesr04(D1,D2.ICU) ?


That's the Viper style, being cross-platform is an hard job  :smiley: 
With this signature, users can always check, reading the code, if the used hardware has the feature required for running that code.

@Giacomo any idea for the lib publishing reported issue?

I think should be added the ability to clone a library. For example I created a local library for the sensor sr04. It would be nice to be able to clone it as a comunity library to publish it easily.

Furthermore if I edit a library the edit window opens in project editing mode instead of library editing mode: I don’t know if this is right.

here you can find a detailed description of the viper library publishing service.
http://doc.viperize.it/core.viper.ide/r0.3.5/

most of your questions  are answered there :smile: 

I published the sr04 library with an example. If I have understood when a Viper admin will check it I will be able to import it:

from community.mynamespace.sr04 import sr04

And the library is live  B)

Thank you very much!

So cool  :o
Thanks to Viper comunity  :slight_smile: