multi-tasking ping sonars

Discussion specific to the 24-pin ZX microcontrollers, e.g. ZX-24r, ZX-24s and ZX-24t.
Post Reply
LtDan80
Posts: 7
Joined: 11 February 2008, 10:58 AM

multi-tasking ping sonars

Post by LtDan80 »

The current problem I am having is that after about 3 minutes of running the code, it begins to malfunction. The chip randomly gives a high reading and a low reading to either sensor. It works perfect before this. i am trying to figure out if it is an RC time constant problem, a problem with the RAM getting filled, or a problem with the code. Hese is what I have.

Code: Select all

Option Explicit 
Dim Stack1(1 To 48) As Byte 
Dim Stack2(1 To 48) As Byte 
Dim Width1 as Single, Feet1 as Single, Inches1 as Single 
Dim Width2 as Single, Feet2 as Single, Inches2 as Single 
'--------------------------------------------------- 
Public Sub Main() 
  CallTask "SonarTask1", Stack1 
  Call Sleep(0.2) 
  CallTask "SonarTask2", Stack2 
  Call Sleep(0.2) 
  Do 
    Call Sleep(120.0) 
  Loop 
End Sub 

'------------------------------------------------------------------------------------- 
Private Sub SonarTask1() 
  Do 
    Call PulseOut(17, 3.0, 1) 
    Call PulseIn(17, 1, Width1) 
    Feet1 = Width1 * 550.0 'assuming 1100 feet per sec 
    Inches1 = Feet1 * 12.0 
    Debug.Print CStr(Inches1) 
    Call Delay(0.3) 
    If Inches1 <5.0 then 
      Call Putpin &#40;25,0&#41; 'turns on LED pin 25, ZX-24a 
    Else 
      Call Putpin &#40;25,1&#41; 'turns off LED pin 25, ZX-24a 
    End If 
    Call PutPin&#40;17, 1&#41; 
  Loop 
End Sub 

'------------------------------------------------------------------------------------- 
Private Sub SonarTask2&#40;&#41; 
  Do 
    Call PulseOut&#40;18, 3.0, 1&#41; 
    Call PulseIn&#40;18, 1, Width2&#41; 
    Feet2 = Width2 * 550.0 'assuming 1100 feet per sec 
    Inches2 = Feet2 * 12.0 
    Debug.Print CStr&#40;Inches2&#41; 
    Call Delay&#40;0.3&#41; 
    If Inches2 <5.0 then 
      Call Putpin &#40;26,0&#41; 'turns on LED pin 26, ZX-24a 
    Else 
      Call Putpin &#40;26,1&#41; 'turns off LED pin 26, ZX-24a 
    End If 
    Call PutPin&#40;18, 1&#41; 
  Loop 
End Sub 
Thanks for your help, The paper I have decided to do will cover multi-tasking IR and Sonar with the ZX-24a. I hope the paper will be able to help you all later.

Dan
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: multi-tasking ping sonars

Post by dkinzer »

LtDan80 wrote:after about 3 minutes of running the code, it begins to malfunction.
Some of the problems that were brought to your attention still have not been rectified. For example, you're still calling PulseOut() with a delay parameter of 3.0 seconds. It's not clear why you're trying to generate a pulse of 3 seconds but the Ping Sonar definitely doesn't need it. The data sheet (which I recommend that you read thoroughly) indicates a minimum trigger pulse width of 2 uS with a typical trigger pulse width of 5 uS.

Secondly, there is still a problem with the output state at the beginning of the loop. The following code may address these problems.

Code: Select all

Private Sub SonarTask1&#40;&#41;
  Const pingPin as Byte = 17
  Const ledPin as Byte = 25
  Const triggerPulse as Single = 5.0e-6
  Do
    Call PutPin&#40;pingPin, 0&#41;
    Call PulseOut&#40;pingPin, triggerPulse, 1&#41;
    Call PulseIn&#40;pingPin, 1, Width1&#41;
    Feet1 = Width1 * 550.0 'assuming 1100 feet per sec
    Inches1 = Feet1 * 12.0
    Debug.Print CStr&#40;Inches1&#41;
    Call Delay&#40;0.3&#41;
    If Inches1 <5.0 then 
      Call Putpin &#40;ledPin,0&#41; 'turns on LED pin 0, MMC_BS2
    Else
      Call Putpin &#40;ledPin,1&#41; 'turns off LED pin 0, MMC_BS2
    End If
  Loop
End Sub
Note, also, that I introduced constants for the pins. This not only improves the readability of the code, it will facilitate simple conversion later to using a single parameterized task routine to handle both sonar tranducers.
- Don Kinzer
LtDan80
Posts: 7
Joined: 11 February 2008, 10:58 AM

Post by LtDan80 »

Don, I restructured the code. It now reads:

Code: Select all

Dim Stack1&#40;1 To 36&#41; As Byte 
Dim Stack2&#40;1 To 36&#41; As Byte 
Dim Width1 as Single, Feet1 as Single, Inches1 as Single 
Dim Width2 as Single, Feet2 as Single, Inches2 as Single 

'--------------------------------------------------- 
Public Sub Main&#40;&#41; 
  CallTask "SonarTask1", Stack1 
  Call Sleep&#40;0.1&#41; 
  CallTask "SonarTask2", Stack2 
  Call Sleep&#40;0.1&#41; 
  Do 
    Call Sleep&#40;60.0&#41; 
  Loop 
End Sub 

'------------------------------------------------------------------------------------- 
Private Sub SonarTask1&#40;&#41; 
  Const pingPin as Byte = 17 
  Const ledPin as Byte = 25 
  Const triggerPulse as Single = 5.0e-6 
  Do 
    Call PutPin&#40;pingPin, 0&#41; 
    Call PulseOut&#40;pingPin, triggerPulse, 1&#41; 
    Call PulseIn&#40;pingPin, 1, Width1&#41; 
    Feet1 = Width1 * 550.0 'assuming 1100 feet per sec 
    Inches1 = Feet1 * 12.0 
    Debug.Print CStr&#40;Inches1&#41; 
    Call Delay&#40;0.3&#41; 
    If Inches1 <5.0 then 
      Call Putpin &#40;ledPin,0&#41; 'turns on Red LED pin 25, ZX-24a 
    Else 
      Call Putpin &#40;ledPin,1&#41; 'turns off Red LED pin 25, ZX-24a 
    End If 
  Loop 
End Sub 

'------------------------------------------------------------------------------------- 
Private Sub SonarTask2&#40;&#41; 
  Const pingPin as Byte = 18 
  Const ledPin as Byte = 26 
  Const triggerPulse as Single = 5.0e-6 
  Do 
    Call PutPin&#40;pingPin, 0&#41; 
    Call PulseOut&#40;pingPin, triggerPulse, 1&#41; 
    Call PulseIn&#40;pingPin, 1, Width2&#41; 
    Feet2 = Width2 * 550.0 'assuming 1100 feet per sec 
    Inches2 = Feet2 * 12.0 
    Debug.Print CStr&#40;Inches2&#41; 
    Call Delay&#40;0.3&#41; 
    If Inches2 <5.0 then 
      Call Putpin &#40;ledPin,0&#41; 'turns on Green LED pin 26, ZX-24a 
    Else 
      Call Putpin &#40;ledPin,1&#41; 'turns off Green LED pin 26, ZX-24a 
    End If 
  Loop 
End Sub 
I am still getting the same error however. It is very random with when it fails, after 10 trials, I have had everything from it failing at 46 seconds, up to running over 10 minutes perfectly fine and then freezing. I have not touched anything in that time and have just been letting the Sonar's read off of a wall. Any other suggestions would be great.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

LtDan80 wrote:I restructured the code
When you post code, please wrap it in code /code tags. The easiest way to do this is to select all of the text that is code and click the 'Code' button above the message body edit control. You can also just type 'code' and '/code' each enclosed in square brackets.

You might try increasing the task stack size but I suspect that this will have no effect.

How are you powering the ZX and the Ping sonar? What else is connected, if anything, and how is it powered? Which ZX device are you using?
- Don Kinzer
LtDan80
Posts: 7
Joined: 11 February 2008, 10:58 AM

Post by LtDan80 »

I am using a ZX-24a. The board I am using is a motor mind carrier board. I am using 2 ping sonar's, and it is powered through a 12 volt ac to dc converter. When it enters the MMC it gets regulated down to 5 volts.
mikep
Posts: 796
Joined: 24 September 2005, 15:54 PM

Re: multi-tasking ping sonars

Post by mikep »

LtDan80 wrote:The current problem I am having is that after about 3 minutes of running the code, it begins to malfunction. The chip randomly gives a high reading and a low reading to either sensor. It works perfect before this.
I'm not quite sure what "before this" means. If something previously worked then you should be able to see what changed.

My guess is that now and again the two sonars are interfering with each other and PulseIn() is getting confused. You could verify this by only starting one task or the other. It might be better to fire both sonars in one task, one after the other rather than have separate tasks for each one.

There are some other code improvements that could be made but we will save that for later. ZBasic is quite different to Stamp Basic and I think you will find it has several advantages. BTW Don't worry too much about RAM - you have a huge amount on the ZX-24a compared the Basic Stamps.
Mike Perks
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

LtDan80 wrote:I restructured the code.
After thinking about it some more, I'm sure that you're going to need a mechanism to ensure atomic execution of the PulseOut/PulseIn sequence. Otherwise, you run the risk of a task being suspended between the two calls.

There are two mechanisms available for serializing this sequence - using a semaphore or locking the task. Note, however, that neither of these methods will help if you eventually add WaitForInterval() or WaitForInterrupt() calls. Here's how the code would look using task locking:

Code: Select all

    Call LockTask&#40;&#41;
    Call PulseOut&#40;pingPin, triggerPulse, 1&#41;
    Call PulseIn&#40;pingPin, 1, Width2&#41;
    Call UnlockTask&#40;&#41;
- Don Kinzer
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

For the last 24 hours I've had a variation of your program running here. I have only one of the Ping devices so it's not quite the same setup that you have. The code below is what I'm using. It has two tasks that use the same Ping device.

Code: Select all

Dim Stack1&#40;1 To 48&#41; As Byte 
Dim Stack2&#40;1 To 48&#41; As Byte 
Dim Width1 as Single, Feet1 as Single, Inches1 as Single 
Dim Width2 as Single, Feet2 as Single, Inches2 as Single 
'--------------------------------------------------- 
Public Sub Main&#40;&#41; 
  CallTask SonarTask&#40;1&#41;, Stack1 
  Call Sleep&#40;0.2&#41; 
  CallTask SonarTask&#40;2&#41;, Stack2 
  Call Sleep&#40;0.2&#41; 
  Do 
    Call Sleep&#40;0&#41; 
  Loop 
End Sub 

'------------------------------------------------------------------------------------- 
Private Sub SonarTask&#40;ByVal id as UnsignedInteger&#41;
  Const trigPin as Byte = 5
  Const trigPulse as Single = 5.0e-6
  Dim LED as Byte
  LED = IIF&#40;id = 1, 25, 26&#41;
  Do
	Dim width as Single
    Call PutPin&#40;trigPin, 1&#41;
	Call LockTask&#40;&#41;
    Call PulseOut&#40;trigPin, trigPulse, 1&#41; 
    Call PulseIn&#40;trigPin, 1, width&#41; 
	If &#40;id = 1&#41; Then
	  Width1 = width
      Feet1 = Width1 * 550.0 'assuming 1100 feet per sec 
      Inches1 = Feet1 * 12.0
	Else
	  Width2 = width
      Feet2 = Width2 * 550.0 'assuming 1100 feet per sec 
      Inches2 = Feet2 * 12.0
	End If
    Debug.Print CStr&#40;id&#41;; " &#58; "; Fmt&#40;Inches2, 1&#41; 
    If Inches2 < 5.0 then 
      Call Putpin &#40;LED,0&#41; 'turns on LED pin 26, ZX-24a 
    Else 
      Call Putpin &#40;LED,1&#41; 'turns off LED pin 26, ZX-24a 
    End If 
	Call UnlockTask&#40;&#41;
    Call Delay&#40;0.3&#41; 
  Loop 
End Sub
- Don Kinzer
Post Reply