libpruio (BB D/A - I/O fast and easy)

Headers, Bindings, Libraries for use with FreeBASIC, Please include example of use to help ensure they are tested and usable.
Post Reply
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: libpruio (BB D/A - I/O fast and easy)

Post by TJF »

Hi Dinosaur!

Sorry, no TIMER examples yet. Currently that's work in progress. I'm not happy with the setValue parameters. I think finally Dur1 should set the full duration of the period, while Dur2 should specify the part timer for high state. Also I want to use the TIMER-SS for frequency measurement (but it seems that I cannot get the duty cycle from the hardware).

In case of controller code running on the ARM under LINUX variations of 400 uSec are usual. Use the second PRU for more accurate timing.

To be honest, I don't really understand your target. So I cannot give any hints for optimization.

Regards
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF

No panic on anything, if you get the timer SetValue working correctly, it will be used.
To be honest, I don't really understand your target. So I cannot give any hints for optimization.
To be able to;
1: Set & Read GPIO
Done & working

2: Set a Timed Pulse output (ie: P8_07 Hi for 350 mSec)
Can't get beyond 0.2 mSec.

3: Run a Stepper directly from BBB. (Your example allows that)
My cape will allow high current device.

4: Run a Servo by pulsing fixed number of pulses.
This seems to be the hardest to achieve using either Cap or Qep.
I can run pwm and then poll & stop the pwm.
I can run pwm and "gate" pulses for fixed duration.(with another output)

In all of them I need to be able accurately time the "gate" or "Stop pwm".

If I can achieve the above 4 points, then I have an viable alternative to test in the field.

Regards

https://www.youtube.com/watch?v=R7bgAo0EINI
These are the motors I use.
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF

Is this a fault or something I have mis-understood.

If I set P9-14 Pwm1A to 50 Hz
then set P9-16 PWM1B to 5 Hz

Both channels run at 5Hz.

So, to gate 50Hz for the duration 5Hz, I have had to use P9-14 and P8-13.
However, that doesn't allow me to sync the channels.
Edit: Sorry, each set of pwm's can only have one frequency, and Sync applies to all pwm's

Regards
EDIT: Combing through the documentation, I am trying to clarify the relationship.
In pseudo code.
1: Stopping the pwm's with Sync(&b000)
2: Setting the "registers" for the pwm values with ? Pwm->SetValue(Pin,Hz,Du)
3: Running config to upload the configuration to Pruss
4: Starting the Clk's with Sync(&B111)

Two problems:
after step 2, the pwm's are already running (oscilloscope shows pulses)
what are the parameters for Config ? The description for config is all about ADC's ?
Is the order of my calls incorrect ?
EDIT2:
It appears that a pwm does not get cancelled (with Pwm->SetValue(Pin,0,0)) until a cycle is completed.
So cancelling it as soon as the pwm goes low does not take affect until the total low time is completed.
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: libpruio (BB D/A - I/O fast and easy)

Post by TJF »

Hi Dinosaur!
Dinosaur wrote:2: Set a Timed Pulse output (ie: P8_07 Hi for 350 mSec)
Can't get beyond 0.2 mSec.
I found and fixed a mis-scaling bug. But I'm also dealing with hardware issues here. My code is runing well when the TIMERSS is continuously repeating a pulse train (like PWM). But when I set up a single shot configuration (TCLR:AR = 0), the output pin timer_pwm doesn't get toggled (in special cases it partially works, but only once). This seems to be a hardware bug, I've to ask the CPU manufacturer (Texas Instruments). But I'm not very confidend. I reported a similar bug in the PWMSS.QEP module and didn't get any answer.
Dinosaur wrote:4: Run a Servo by pulsing fixed number of pulses.
This seems to be the hardest to achieve using either Cap or Qep.
I can run pwm and then poll & stop the pwm.
I can run pwm and "gate" pulses for fixed duration.(with another output)
CAP wont help mutch, it only gives speed information.

Unfortunately the websites about the servos are only advertising -> no technical information. When the servos have a QEP sensor and you can get the signals (at least A + B pulse train, perhaps also the synchronization pulse I), then libpruio can measure the shaft position and speed. You wont need to count pulses. Instead implement a closed loop position controller.

If there is no QEP sensor (or no sinals), I'd use a fast PRU.GPIO to generate the PWM output by software, which makes it easy to count the pulses.
Dinosaur wrote:Is this a fault or something I have mis-understood.

If I set P9-14 Pwm1A to 50 Hz
then set P9-16 PWM1B to 5 Hz
This is a hardware limitation. Both channels (A + B) on a PWMSS.PWM module are running at the same frequency, the second configuration overrides the first. See http://users.freebasic-portal.de/tjf/Pr ... ml#sSecPwm

When you need different frequencies you've to either use a channel on a different PWMSS.PWM module, or generate the pulse train by TIMERSS or PWMSS.CAP module (at another header pin).
Dinosaur wrote:what are the parameters for Config
You mis-understand that function. Call PruIo::config() only once in your code!!! It configures all hardware registers and then starts the libpruio main loop. When you call it twice, you'll loose all current measurements.

In your code do all hardware setup before that call. Design your code so that you don't need any set up after that call. (libpruio allows to configure after that call, because in special cases re-configuration is unavoidable, ie. for a three-state GPIO = input and output at the same pin.)

Regards
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF

Many thanks for you detailed reply, will have to think about how to handle the pulse count.
I found and fixed a mis-scaling bug.
Will you update your site so that I can test it as well ?

Received my boards yesterday, so will solder one together and test as well.

Regards
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: libpruio (BB D/A - I/O fast and easy)

Post by TJF »

Dinosaur wrote:Will you update your site so that I can test it as well ?
Yes, I will. The question is when. Also I'll have to fix the single shot issue. Either I remove this feature (from code and docs). Or - my prefered solution - I find a way to make it work. But the later may take some time.

Regards
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF

Fixing the single shot would be preferable, no rush , I will keep developing (and also look for alternatives)

One further question on Config()
I notice that the behaviour changes if I use Config(0,0) or (1,0) or any combination thereof.
What is the correct way.

Can I call config after setting pwm with Freq & Dur as 0
and then later in the code change the freq & Dur ?

Calling Config after setting pwm with a freq & dur causes a delay which affects the pwm.

Regards
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF

Additional information for you.

The code below does NOT produce any output to the Picoscope the first time I run it after powering the BBB On.
Every time there after it works perfectly. (Will email a pdf to you with Picoscope output.)

Code: Select all

#INCLUDE ONCE "BBB/pruio.bi"
#INCLUDE ONCE "BBB/pruio_pins.bi"
#DEFINE P20 P8_11
Dim Xq as UInteger
'--------------------------------------------------------'
'A 500 Hz pulse train gated for 20 mSec
'Connect Output P8_13 to Input P8_11 to act as Gate
'Connect Output P9_14 to Led/CRO to see how many pulse we got
'--------------------------------------------------------'
Dim Shared io as PruIo
WITH io
    IF .Gpio->config(P20, PRUIO_GPIO_IN_0) THEN ?"failed setting P20 (" & *.Errr & ")"
    IF .Errr THEN Goto Err_End
    .Pwm->Sync(&b111)
    .Pwm->setValue(P8_13, 0, 0)                        'Set Gate to allow pulses'
    .Pwm->setValue(P9_14, 0, 0)                        'Set Pulses to be counted'
    IF .config(1,0) THEN Goto Err_End

    .Pwm->setValue(P8_13, 50, .9)                       'Set Gate to allow pulses'
    .Pwm->setValue(P9_14, 500,.5)                       'Set Pulses to be counted'
    While .Gpio->Value(P20) = 0 :Wend                   'Make sure Gate went to 0 (Hi)'
    While .Gpio->Value(P20) = 1 :Wend                   'Wait whilst it is Hi to let pulses out'

    .Pwm->Sync(&b000)
    .Pwm->setValue(P8_13, 0, 0)
    .Pwm->setValue(P9_14, 0, 0)
END WITH
End

Err_End:
    Print "Error End"
    End
Putting the "Gating" pwm at 0.95 duty cycle allows me to only run the pulses whilst i/p is Hi.

With regard to Servo applications, the link I showed before are for Servo's that have the controller embedded in them.
I use them for Augers, where we don't care about position.
Depositing frozen fruit cubes into Smoothies at a specific target weight.
I simply use pulses as clocks to rotate the servo a fixed number of rotations.
The rotations per pulse are adjustable, so quite flexible.

Regards
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: libpruio (BB D/A - I/O fast and easy)

Post by TJF »

Hi Dinosaur!
Dinosaur wrote:Fixing the single shot would be preferable, no rush , I will keep developing (and also look for alternatives)
One shot mode by hardware is a No-Go. Now it's implemented by software.

And I found and fixed a bunch of other bugs and did some fine tuning regarding the TIMER and PWM timings. The new packages 0.6.4c are available at the PPA.

Regarding your code: I don't even start code that doesn't check for error messages. So I added the missing code, and since I don't have a scope, I added some code for counting pulses by a further GPIO input (needs wiring P9_14 to P9_16), ending up with

Code: Select all

#INCLUDE ONCE "BBB/pruio.bi"
#INCLUDE ONCE "BBB/pruio_pins.bi"
#DEFINE P20 P8_11
#DEFINE REF P9_16
'--------------------------------------------------------'
'A 500 Hz pulse train gated for 20 mSec
'Connect Output P8_13 to Input P8_11 to act as Gate
'Connect Output P9_14 to Led/CRO to see how many pulse we got !! AND REF !!
'--------------------------------------------------------'
DIM SHARED io AS PruIo
VAR freq = 500. _ ' the pwm frequency
  , duty = .5 _   ' the duty cycle
  , cnt = 9 _     ' the number of pulses
  , tim = (cnt - .25 * duty) / freq ' the time for the pulse train (Gate time) in [ms]
DIM AS UInt8 v(cnt * 4050) ' array to store output
WITH io
  WHILE .Errr = 0
    IF .Errr THEN EXIT WHILE
    IF .Gpio->config(P20, PRUIO_GPIO_IN_0) THEN ?"failed setting P20 (" & *.Errr & ")" : EXIT WHILE
    IF .Gpio->config(REF, PRUIO_GPIO_IN_0) THEN ?"failed setting P9_16 (" & *.Errr & ")" : EXIT WHILE
    IF .Pwm->Sync(&b000) THEN ?"failed pwm sync off (" & *.Errr & ")" : EXIT WHILE
    'Set Gate to allow pulses (PWMSS-2:B)'
    IF .Pwm->setValue(P8_13,   1., tim) THEN ?"failed pwm P8_13 (" & *.Errr & ")" : EXIT WHILE
    'Set Pulses to be counted (PWMSS-1:A)'
    IF .Pwm->setValue(P9_14, freq, .5 ) THEN ?"failed pwm P9_14 (" & *.Errr & ")" : EXIT WHILE
    'Switch off PWM clock
    IF .config(1) THEN ?"failed hardware config" : EXIT WHILE

    VAR x = 0
    IF .Pwm->Sync(&b110) THEN ?"failed pwm sync on (" & *.Errr & ")"
    '' ORG:
    'WHILE .Gpio->Value(P20) : WEND
    'IF .Pwm->Sync(&b000) THEN ?"failed pwm sync off (" & *.Errr & ")"
    '' NEW: measuring pulses by GPIO
    FOR i AS INTEGER = 0 TO UBOUND(v)
      v(i) = .Gpio->Value(REF)
      IF x THEN CONTINUE FOR
      IF .Gpio->Value(P20) THEN CONTINUE FOR
      IF .Pwm->Sync(&b000) THEN ?"failed pwm sync off (" & *.Errr & ")" : EXIT FOR
      x = i
    NEXT

'' evaluate results
    VAR n = v(0), o = 0
    FOR i AS INTEGER = 1 TO UBOUND(v)
      IF v(i) = v(i - 1) THEN CONTINUE FOR
      ?i,*IIF(v(i), @"0 -> 1", @"1 -> 0"), n, i - o
      n += v(i) ' count at the high->low transition
      o = i
    NEXT
    ?"pulses: ";n,"v()-rest: "; UBOUND(v) - x
    END
  WEND

  ? "Error End (" & *.Errr & ")"
END WITH
END(1)
Here this code is working - after boot as well as in all further runs.

Note: Instead of the GPIO gate, you can use the trip zone input/submodule (lower latency, higher security in case of ARM software crash).

Regards
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF

Many thanks for the update and time you are spending on this.
It is worth noting that from all the browsing I have done, there are very few libraries for the BBB.
Considering that so many young students are using (or trying to) Arduino & RPi and BBB, your effort will
result in more FB participants.

Personally I have been busy interfacing the HX711 24 bit A2D converter to your library by bit bashing.
I know asm code in the PRUSS will beat it hands down, but at this stage that is beyond my skill level.
I will receive the boards by Tuesday and will prove one way or the other that my method will work.
Will let you know.
The high current cape works well except for not being able to switch the outputs Off at boot time.
Have ordered an updated board that will also arrive early next week.
One shot mode by hardware is a No-Go. Now it's implemented by software.
Will read and test over the next few days.
I don't even start code that doesn't check for error messages.
That is almost my sentiment,
except that when initially testing I tend to leave that out for more mundane Print messages, which I remove to post simplified code.
My software has an extensive "ErrControl" module that I usually apply to the finished product for the users benifit.
you can use the trip zone input/submodule
I have been interested in Tripzone (only one available) for some time, but failed to find example code
on how to use it. But will perservere.
For the moment I really will concentrate on confirming that the various functions in the Library work for me as per doc's.

Regards
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF

Running your example code "as is" I am having the same problem as I did before.
1. Sync of clocks doesn't seem to work reliably.
The "Gate" will be different by 1/2 cycle of the clock, and I think this is caused by the instructions:

Code: Select all

    IF .Pwm->Sync(&b000) THEN ?"failed pwm sync off (" & *.Errr & ")" : EXIT WHILE
    'Set Gate to allow pulses (PWMSS-2:B)'
    IF .Pwm->setValue(P8_13,   1., tim) THEN ?"failed pwm P8_13 (" & *.Errr & ")" : EXIT WHILE
    'Set Pulses to be counted (PWMSS-1:A)'
    IF .Pwm->setValue(P9_14, freq, .5 ) THEN ?"failed pwm P9_14 (" & *.Errr & ")" : EXIT WHILE
    'Switch off PWM clock
    IF .config(1) THEN ?"failed hardware config" : EXIT WHILE
Setting P8_13 immediately starts that Pwm going before you get a chance to start P9_14.
If Sync worked then there would never be a time when the two starts, would start at different times.
Although if the first Pwm is already running, then the second Pwm will try to Sync on the next "fall time" ie: 1/2 cycle later.
I proved this by swapping the order of Pwm statements.

2. I have not found a way to STOP any Pwm immediately.
For example your code as is, runs the clocks to be counted continuously until the io is destroyed.(at End)
I can get it to stop earlier but not reliably at the desired count by reconfiguring the port to Gpio->Config (P9_14, PRUIO_GPIO_OUT0)
then I get 17 pulses.
Note that the Gate pulse is always within 30 uSec of the target (17.78 instead of 17.75 mSec)
Increasing the Duty cycle to 0.95 reduces pulses by about 3, but still about 14 pulses.

In my logic (if possible) is should look like this:
i) Stop Clk pulses
ii) Setup Pwm's
iii) Set Sync
iv) Config
v) Start Clocks
vi) Count Pulses OR look for Gate Lo.
vii) Stop Clk.

I know that the Pulse count feature is something specific to my needs, but in trying to achieve that
I am seeing what could be problems in the library.

Regards

Edit: The more I test, the more I am convinced the problem is with Sync(&b000)
It does not stop the clocks.
If you put a SLEEP before Sync(&b110) the Scope shows both Pwm's have started.
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF

Below result of my One Shot timer test after the changes you made.
Conclusions in comments.

Code: Select all

#INCLUDE ONCE "BBB/pruio.bi"
#INCLUDE ONCE "BBB/pruio_pins.bi"
'==================================================================
'This test sets O/P P8-07 for single shot of Dur1
'First set P8_07 to Gpio Output to secure normal state.(Hi or Lo)
'If setting is Lo, set Mode = 2 ,Dur1 (Lo period) won't be visible.
'If setting is Hi, set Mode = 3 ,Dur1 (Hi period) won't be visible.
'NOTE: First time it is run after state change 2 pulses can occur.
'Dur1 = Space Time in mSec ie: 1.0
'Dur2 = Pulse Time in mSec ie: 3.0 is 3 mSec.


'
'CONCLUSION: 0.005 mSec pulse @ 90.9 Khz is maximum speed output due to
'            limitation of Total (Dur1 + Dur2) cannot be less then 0.011 mSec.
'            any lower and SetValue will produce Error.
'==================================================================
Dim Shared As Single Dur1 , Dur2
Dim Shared as SHORT Mode
VAR io = NEW PruIo()
    WITH *io
        IF .Errr THEN Goto Err_End
        IF .Gpio->config(P8_07, PRUIO_GPIO_OUT0) THEN ?"failed setting P8.07 (" & *.Errr & ")"
        IF .config() THEN Goto Err_End
        Dur1 = 1
        Dur2 = 1
        Mode = 2
        If .Tim->SetValue(P8_07, Dur1, Dur2, Mode) Then
            Goto Err_End
            Print "Errer 2"
        EndIf
''      'Getting Values Dur1 & Dur2 doesn't appear to work
''      'immediately returning a value of -4.165478e-05
''        Do
''            If .Tim->Value(P8_07, @Dur1, @Dur2) Then Goto Err_End
''            If Dur2 < 0 Then exit do
''            Print "Dur1= ";Dur1, "Dur2= ";Dur2
''        Loop
        Print "Dur1= ";Dur1, "Dur2= ";Dur2
    END WITH
    Sleep
    Delete io
    End
Err_End:
    Print "Error End"
    Delete io
    End
EDIT: Additional info.
Sorry for the early conclusion, but I am aware of getting info to you asap in case you are already debugging.
The confusion came in with an extra short pulse.
At any duration of Dur1 there is a High Pulse at the start of the cycle.
Almost like the code was making up it's mind if the first Dur1 should be Hi or Lo.

The combined Dur1 + Dur2 has to be > 0.010 mSec.
If Dur1 = 0.005 and Dur2 = 0.005 it will Err on SetValue.
Change either one to 0.006 and it works.

EDIT2: Tested by making Dur1 < 1.0
Basically the extra pulse moves closer to the main pulse (as expected), until I make the Dur1 < 0.007 then I will get up to 3 main pulses with a space gap of 0.006 or less.
Knowing the limitations imposed by the clock driving this feature and the software associated with it,
you may need to tell me what the limits are.

PS: Sent you a pdf of the CRO output.
Regards
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: libpruio (BB D/A - I/O fast and easy)

Post by TJF »

Hi Dinosaur!
Dinosaur wrote:...
ii) Setup Pwm's
iii) Set Sync
iv) Config
...
Which Sync?
Dinosaur wrote:1. Sync of clocks doesn't seem to work reliably.
Did you update the LKM package?
Dinosaur wrote:Change either one to 0.006 and it works.
Also changing either one to 0.0050001 works. Read about float numbers.
Dinosaur wrote:At any duration of Dur1 there is a High Pulse at the start of the cycle.
I'll check this. My former testing was based on LED output. I've to find another output method. Thanks for the feedback!

Regards
Dinosaur
Posts: 1478
Joined: Jul 24, 2005 1:13
Location: Hervey Bay (.au)

Re: libpruio (BB D/A - I/O fast and easy)

Post by Dinosaur »

Hi TJF
Which Sync?
io.Pwm->Sync(&b110)
Did you update the LKM package?
Yes, All packages are version c .
I'll check this. My former testing was based on LED output. I've to find another output method.
I am Happy to keep testing if you supply the changed code. The CRO (old fashioned speak for Cathode Ray Oscilloscope) I use is a Picoscope.
If I test with my Fet O/P board attached, then the pulses are rounded a bit at the higher speed.

Regards
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: libpruio (BB D/A - I/O fast and easy)

Post by TJF »

Dinosaur wrote:
Which Sync?
io.Pwm->Sync(&b110)
This is
Dinosaur wrote:...
v) Start Clocks
...
Dinosaur wrote:
Did you update the LKM package?
Yes, All packages are version c .
Please post the output from

Code: Select all

X=/sys/devices/platform/libpruio/state ; echo "ff06" > $X ; cat $X
Regards
Post Reply