B4R Question QTR Sensor Read

KiloBravo

Active Member
Licensed User
I am trying to write some code to read a QTR-HD-01RC Reflectance Sensor (https://www.pololu.com/product/4101).
The faq says to:


Set the I/O line to an output and drive it high.
Allow at least 10 μs for the sensor output to rise.
Make the I/O line an input (high impedance).
Measure the time for the voltage to decay by waiting for the I/O line to go low.

So something like this.
B4X:
Sub Init_QTR
    QTR.Initialize(dp.D1,QTR.MODE_OUTPUT)
    QTR.DigitalWrite(True)
    Init_Time = Micros
    QTR_Flag = False
'    DelayMicroseconds(10) <<< Didn't think I needed this tried with and without it.
    QTR.Initialize(dp.D1,QTR.MODE_INPUT_PULLUP)  <<<  Will this even work ?
End Sub

I then tried various flavors of Timers or Loopers and doing a digitalread of the QTR pin with no results.
The fact says:
With a strong reflectance, the decay time can be as low as a few microseconds; with no reflectance, the decay time can be up to a few milliseconds. The exact time of the decay depends on your microcontroller’s I/O line characteristics.

The LOOPER seemed to be capable of a couple hundred loops per millisecond. Is the DigitalRead fast enough to catch a decay of 120us ? They mentioned that was about the average decay for a black background as opposed to a white background that could take up to 2.5 ms.

Any suggestions ?

Thanks !
 

tigrot

Well-Known Member
Licensed User
Longtime User
The datasheet :
  1. Turn on IR LEDs (optional).
  2. Set the I/O line to an output and drive it high.
  3. Allow at least 10 μs for the sensor output to rise.
  4. Make the I/O line an input (high impedance).
  5. Measure the time for the voltage to decay by waiting for the I/O line to go low.
  6. Turn off IR LEDs (optional).
line 4 states high impedance and doesn't speak about pullup.
 
Upvote 0

KiloBravo

Active Member
Licensed User
Good suggestions.
I tried it with and without the delay 10 us. My thought being I was doing other "stuff" in the Sub and that was burning cycles before the read.
Somehow in trying different things I switched the input line to a pullup. Now that you pointed that out I realized that was not a good idea.
Time try some new code !
 
Upvote 0

KiloBravo

Active Member
Licensed User
Working ! - Thanks Tigrot !

When I pass a card of reflective material with a few strips of black electrical tape to break up the pattern the decay time changes as expected. I did look through there library and the h file. Ultimately, I think the D1 pin is spotty. I have the esp8266 on a proto-board. I soldered a new module and tested it. It worked. I tested the old sensor it worked. I went back to pin D1 from D3 and it was hit or miss. A just cobbled some code together and used an addListener. Pretty ugly code but working.

B4X:
Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    Timer1.Initialize("Timer1_Tick", 3000) '1000ms = 1 second
    Timer1.Enabled = True
    Init_QTR
'    AddLooper("Looper1") // out for now
    QTR.AddListener("Change_state")
End Sub

Sub Init_QTR
    QTR.Initialize(dp.D3,QTR.MODE_OUTPUT)
    QTR.DigitalWrite(True)
    Init_Time = Micros
'   QTR_Flag = False // not used
'    DelayMicroseconds(10) // Add back in if Log statement is removed
    Log("Int Sub -- Cntr = ",Reset_Cntr)
    Reset_Cntr = 0
    Log("Int Sub")
    QTR.Initialize(dp.D3,QTR.MODE_INPUT)
End Sub

Sub Change_state (State As Boolean)
    If State == False Then
        Decay_Time = Micros - Init_Time
        Log("QTR Decay Time = ", Decay_Time)
        Init_QTR
    Else
        Reset_Cntr = Reset_Cntr + 1
    End If
End Sub

Sub Timer1_Tick
    Log("Time Out ")
    Log("Reset_Cntr = ",Reset_Cntr)
    Init_QTR
End Sub
 
Upvote 0

tigrot

Well-Known Member
Licensed User
Longtime User
Working ! - Thanks Tigrot !

When I pass a card of reflective material with a few strips of black electrical tape to break up the pattern the decay time changes as expected. I did look through there library and the h file. Ultimately, I think the D1 pin is spotty. I have the esp8266 on a proto-board. I soldered a new module and tested it. It worked. I tested the old sensor it worked. I went back to pin D1 from D3 and it was hit or miss. A just cobbled some code together and used an addListener. Pretty ugly code but working.

B4X:
Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    Timer1.Initialize("Timer1_Tick", 3000) '1000ms = 1 second
    Timer1.Enabled = True
    Init_QTR
'    AddLooper("Looper1") // out for now
    QTR.AddListener("Change_state")
End Sub

Sub Init_QTR
    QTR.Initialize(dp.D3,QTR.MODE_OUTPUT)
    QTR.DigitalWrite(True)
    Init_Time = Micros
'   QTR_Flag = False // not used
'    DelayMicroseconds(10) // Add back in if Log statement is removed
    Log("Int Sub -- Cntr = ",Reset_Cntr)
    Reset_Cntr = 0
    Log("Int Sub")
    QTR.Initialize(dp.D3,QTR.MODE_INPUT)
End Sub

Sub Change_state (State As Boolean)
    If State == False Then
        Decay_Time = Micros - Init_Time
        Log("QTR Decay Time = ", Decay_Time)
        Init_QTR
    Else
        Reset_Cntr = Reset_Cntr + 1
    End If
End Sub

Sub Timer1_Tick
    Log("Time Out ")
    Log("Reset_Cntr = ",Reset_Cntr)
    Init_QTR
End Sub
Happy for you! Before retirement this was my bread(as we use to say in Italy!).
Mauro
 
Upvote 0
Top