As the title says... Chat on...

User avatar
By bluefireflames
#65150 Hi, I'm trying to read the distance from an hcsr04 sensor. I am having a very difficult time with this and don't really know where to ask for help.
I found this http://www.esp8266.com/viewtopic.php?f=23&t=9341&start=8 to work successfully. However, I don't really understand what is going on. When I tried to implement my own version, my results are all over the place.

In my version, I want to just get one result from the sensor, as opposed to the averaging of results in the example. I don't understand why my one result is always so far off and inconsistent.


Here is a direct copy of the working example code from the link:
Code: Select alllocal gpio, time_start, time_end, trigger, echo = gpio, 0, 0
local sample_count, timer_id

return function(trig_pin, echo_pin, sample_cnt, timer_id, report_cb)
    trigger, echo   = trig_pin or 7, echo_pin or 6
    sample_count, timer_id = (sample_cnt+1) or 4, timer_id or 1   

    local total, i, result = 0, 0, {}

    local function echo_cb(level)
      if level == 1 and result[i] == 0 then
        result[i] = -tmr.now()
        gpio.trig(echo, "down")
      elseif level == 0 and result[i] < 0 then
        result[i] = tmr.now() + result[i];
        gpio.trig(echo, "none")
      else
        gpio.trig(echo, "none") -- anything else turn off interrupts and restart at next sample
        print("DEBUG INT off")
      end
    end
   
    local function measure()
      if i > 0 then -- process last sample
        if result[i] < 0 then
          result[i] = 0
          i = i - 1
          return -- skip a beat to allow the sonar to settle down
        else
          total = total + result[i];
        end
        if i == sample_count then
          tmr.unregister(timer_id)
          for j = 1, sample_count do print(("Sample %u is %u"):format(j,result[j])) end
          total = total - result[1] -- substract sample one because it is usually off...
          return report_cb(total / (58*(sample_count-1)))
        end
      end

      gpio.mode(echo, gpio.INT)
      gpio.trig(echo, "up", echo_cb)
      gpio.write(trigger, gpio.HIGH); tmr.delay(20); gpio.write(trigger, gpio.LOW)
      i = i + 1
    end
   
    for j = 0, sample_count do result[j] = 0 end -- pre-allocate result array

    gpio.mode(trigger, gpio.OUTPUT)
    tmr.alarm(timer_id, 60, tmr.ALARM_AUTO, measure)
    measure()
  end


(correct) sample output:
Code: Select alllocal x = require "test"(1,2,3,1,function(d) print(d) end)
> Sample 1 is 706
Sample 2 is 727
Sample 3 is 712
Sample 4 is 706
12
local x = require "test"(1,2,3,1,function(d) print(d) end)
> Sample 1 is 702
Sample 2 is 706
Sample 3 is 706
Sample 4 is 706
12
local x = require "test"(1,2,3,1,function(d) print(d) end)
> Sample 1 is 694
Sample 2 is 706
Sample 3 is 707
Sample 4 is 707
12


My version:
Code: Select all--variable declarations
local rangingStartTime, echoDuration,distance
local sensorControlPin,sensorDataPin

local function echoRising(level,timestamp)
  rangingStartTime = timestamp
  -- print("Rise detected at echo:"..timestamp)
 

end

local function echoFalling(level,timestamp)
  -- print("Fall detected at echo:"..timestamp)
  echoDuration = timestamp - rangingStartTime
  -- print("echoDuration"..echoDuration)
  -- calculate distance in cm
  distance = echoDuration/58
  print(distance.." cm")

end
local function echoChanged(level,timestamp)
  if level==gpio.HIGH then
    echoRising(level,timestamp)
   gpio.trig(sensorDataPin,"low")
  else
    echoFalling(level,timestamp)
   gpio.trig(sensorDataPin,"none")
  end
end

local function startRanging()
-- send command signal to start ranging
gpio.write(sensorControlPin, gpio.HIGH)
-- timer delay 10us
tmr.delay(20)
--[exit command signal]--
gpio.write(sensorControlPin, gpio.LOW)
end

 

local function main()
--[ SETUP ]--

-- variable storing ranging start time
rangingStartTime = 0

sensorControlPin  = 1
sensorDataPin = 2

gpio.mode(sensorControlPin, gpio.OUTPUT)

gpio.mode(sensorDataPin, gpio.INT)

-- when sensorDataPin changes, do echoChanged
gpio.trig(sensorDataPin,"high",echoChanged)

startRanging()
end


main()


(incorrect) output from my version:
Code: Select alldofile("hcsr04.lua")
> 46 cm

dofile(hcsr04.lua)  Saturday, April 22, 2017  14:35:03

dofile("hcsr04.lua")
> 75 cm

dofile(hcsr04.lua)  Saturday, April 22, 2017  14:35:04

dofile("hcsr04.lua")
> 128 cm


Also, the sensor is working properly, and I can get accurate results using the Arduino IDE.
I could use the Arduino IDE, but I really want to try something I'm not familiar with.

I know I could just copy and use the working lua code, but I'd really like to understand it better.
I've tried detecting gpio.trig on "both", removing my print statements, bringing echoRising and echoFalling into echoChanged, using tmr.now() instead of timestamp...
I'm doing something wrong and I don't know what it is.
Any assistance is greatly appreciated.