Timing conflicts with servo and serout on 08M2+

Eng460

Well-known member
My current project is a speed controller for a small engine, technically a digital speed governor.

It involves provision for adjusting the speed target or set point, measuring the actual engine speed, doing some maths and adjusting a servo to make any necessary speed adjustment.

I use pulsin for the speed measurement, the maths is a bit tricky with the integer maths rules, but all successfully programmed, and after initially setting up the servo with the servo command, I use servopos to adjust its position. A potentiometer and readadc10 provided an adjustable speed setpoint.

Just for fun, I decided to see if this could all be done on and 08M2+. Sure enough, plenty of space for the program, maths basically sorted, may be a bit dodgy algorithm, but seems to all work. Even added a few sertxd statements to display on the computer what was happening at critical points. I remmed out these statements when it was all removed from the computer. All simulates ok.

I was getting a bit of servo jitter that I could not find a rational way to minimise. So I purchased an AXE134 four line display and used the remaining free output pin on the 08M2+ to send data for display, using serout statements. A little experimenting with commands and data statements, lead to a nice readable display. So far so good.

Off to the garage to try it all out. Disappointment! The servo jitter was bad, very bad. So back to section 2. It seems that there is a conflict between time sensitive commands like serout and servo, which results in resetting the servo pulse chain. It does not mention whether pulsin also causes this problem.

Sorry for the long introduction. I hope it all makes sense and gives context to my questions. So at last the questions.

Does the pulsin command also cause conflicts with servo?

Is it possible to get around theses timing conflicts on an 08M2+? Perhaps by making gaps between serout commands, and sending shorter data quantities at one command?

I realise I am asking a lot of a little 08M2+, but it was a fun challenge. Do the bigger chips have more timer facilities that would make them more suitable in this application. I certainly have in my parts box some 14M2 and some 18M2 chips. I believe I also might have a 28X somewhere if all else fails.

I am also wondering if it might be possible to separate out the functions somehow and use two 08M2 chips to avoid the conflict.

Thank you.

Eng460
 

lbenson

Senior Member
There are a fair number of circumstances in which interactions with servo commands cause jitter. In a number of cases this has been fixed by using PULSOUT instead of servo commands.

Try this search: pulsout servo site:https://picaxeforum.co.uk
 

hippy

Technical Support
Staff member
Does the pulsin command also cause conflicts with servo?
Unfortunately it can, as can other commands. All those commands which require the PICAXE to dedicate itself to keeping accurate timing means that it cannot at the same time handle the accurate timing of the servo pulse; the pulse can be stretched longer than it should be at times and this is what causes the jitter.

There may be some scope for synchronising the code execution so any blocking of the servo pulse train doesn't fall within the high period of the pulse which is what causes most problems. You can read the servo pulse on another pin, wait for it to go high and then go low, then do whatever would block it, PULSIN, SEROUT etc, you could even use interrupts for that.

But that's additional complexity and could still be hit and miss, and the same will be true in trying to use any PICAXE.

The best solution is to use a two PICAXE system as you were thinking of. The main PICAXE reading sensors, doing its calculations, updating displays, and instructing the second how to set the servo. That second PICAXE can be an 08M2.

That second PICAXE can then use the PULSOUT command as lbenson suggests which should give rock-solid, jitter free, servo operation. Using a serial link and HSERIN on the servo controlling PICAXE will allow the main PICAXE to take as long as it wants without interfering with the servo control.

That's an extra chip but it may well be easy to insert between your existing servo output and the servo. It's also extra cost but the result will likely be well worth it.
Code:
Symbol SERVO_OUTPUT = C.2

PowerOnReset:
  HserSetup B4800_4, %110

MainLoop:
  Do
    Gosub ReadServoPosition
    Gosub SetServo
  Loop

ReadServoPosition:
  b1 = 1
  HSerIn w0
  If b1 = 0 Then
    w1 = b0
  End If
  Return

SetServo:
  PulsOut SERVO_OUTPUT, w1
  w2 = 2000 - w1
  PauseUs w2
  Return
 

AllyCat

Senior Member
Hi,
(1) Does the pulsin command also cause conflicts with servo?
(2) Is it possible to get around theses timing conflicts on an 08M2+?
(3) Do the bigger chips have more timer facilities that would make them more suitable in this application.
I think the answers are (1) Yes, (2) Perhaps and (3) Yes, but not necessarily more suitable.

I believe the SERVO command can be used on almost any pin (of any chip) so it must be generated by the internal firmware (and interrupts) not by the timer/comparator hardware which is available on only a few specific pins.

The problem is likely to be caused by any commands which disable system interrupts; I don't believe there is a formal list, but it's likely to be any commands that involve accurate timing (in firmware), such as PULSOUT / IN , SEROUT / IN , PAUSEUS (but not PAUSE. etc.), COUNT, etc.. Those commands are common to ALL PICaxes.

SEROUT is a "blocking" command in that it sends all characters before allowing any other instruction to execute, but it's not clear if interrupts are disabled for the whole period. Certainly worth testing with single or only short strings of characters, or in the extreme, throwing single characters directly at HSEROUT.

It's said that the width of the servo pulses is much more important than their spacing, so a software polling (or interrupt) loop using PULSOUT might be a solution. PWMOUT is also a possibility, but only on a few specified pins, with less width resolution and the nominal 20 ms period is not quite achievable. Two 08M2s is a possibility, but they still need to communicate with each other somehow (i.e. not SERIN/OUT, but perhaps HSERIN/OUT ?).

Cheers, Alan.
 

Eng460

Well-known member
Hi Ibenson, thank you for your quick reply. A couple of variations on that search query quickly returned many pages of results. Even in home lockdown, I do not have time to read them all, but by carefully scanning the previews, and reading the more relevant ones, I picked up a number of useful pointers to help my understanding of the issues involved.

Hi Hippy, thank you. That looks like a rock solid solution that is both practical and will always work. For one hobby project the cost of using an extra 08M2+ out of my parts box is not so important. I even have a spare project board, and in this case function is all important while space is not. The “series with the servo“ approach looks very practical.

I can see a big part of my problem is my simplistic approach of sending the command control, followed immediately by the full 20 bytes of data each time I update the display, a simple beginners error.

I guess that I don’t need to keep resending the labels, and if I just jump to the line position and send the data, three or four bytes at the most, it should help. Also I can see that the time it takes for pulsin to time out when the engine stops is the reason it sits there with the servo jiggling every second or so.

I can try modifying those issues, but I can now see that those will likely be stop gap measures that may still be hit and miss. I will definitely move to the two chip solution.

It would have been amazing to implement the concept with just an 08M2+, but not surprising that a more complex solution was required. You have clearly answered the basic question of whether I should have just used a larger chip. That will save a lot of fruitless trial and error and the associated frustration.

I will start working on some program and layout ideas and let you know how I go. Will be a day or two. I assume that the specific servo commands, while making it very easy for a beginner, use more of the chips resources and capability than the direct pulsout command.

Hi AllyCat, thank you. That certainly adds to my understanding of the issues. Like most complex problems, there is no simple one sentence, all “in a nut shell” answer.

Hi Buzby, thanks for the reminder about appendix 4. I am not specifically using interrupts, but the “interrupt driven” part of your description gives the vital clue.

Eng460
 

hippy

Technical Support
Staff member
It would have been amazing to implement the concept with just an 08M2+, but not surprising that a more complex solution was required. You have clearly answered the basic question of whether I should have just used a larger chip.
Unfortunately the single chip solution is as unavoidably difficult as it is having one secretary who, no matter how good they are, can still only do one thing at once. If they are meant to be answering calls at their desk they can't do that when they've been sent down to the lobby to wait for a mail delivery.

Only when things interleave will it all be fine. But at some point the two will collide with one of the callers having to wait which is what the servo jitter amounts to.

Even with a secretary who can run at light speed and be where they need to be they won't be able to do the other while still handling the first. If they rush downstairs and grab the mail while answering a call they'll miss part of that call.

So you basically need two or more secretaries and no PICAXE chip has enough to do what the project requires.

Sending less data to the display etc will improve things, is like saying keep phone calls short so there's less chance of collision when mail arrives but it is only an improvement. Reduces the amount of jitter but won't remove it entirely.
 

Eng460

Well-known member
Thanks Hippy, that is a great analogy. I guess I was hoping that there was a larger chip that actually employed two secretaries. But that has been clearly answered now. So it‘s down to some development, but no big leaps from what I have already done, so I will get there. Your information on how to implement the two chip solution was the vital missing link, so thank you so much for that.

I am just finding that at the moment, I not only wonder how I ever fitted in work before I retired, but also how I fitted so much else in retirement, as now I am not even watching as much TV as before the crisis. But I will come back and report on how it goes.

Eng460
 

Eng460

Well-known member
I have now made some progress on implementing Hippy’s two chip solution for my project. The supplied code was extremely helpful in explaining the necessary steps for using the hserout (C.0) and hserin commands (C.0). Thank you Hippy.

I have identified the correct pins for these commands and made a new board for the servo driver. Moved the servo power supply leads (separate from the Picaxe supply) to the new board, and written a little program. I assume I don’t need the hserout function on this board. Both boards are using an 08M2+ chip, and each has the programming jack and required resistors. I used a three wire arrangement like a servo connection to connect the two 0 volt rails, and convey 5 V and data to the second board.

Now for a servo command I only need one byte to give the maximum allowable 255, and so I believe I might not need any of the routine for retrieving multiple bytes.

Hence, the program reduces to the following key commands -

First the setup and symbol commands in the init: routine -


Code:
Symbol servo_output =C.2    ‘C.2 is the data out to the servo

Hsersetup B4800_4, %10

‘Then for the main routine -

Do

Hserin b0

Pulsout servo_output, b0

W1= b0

W2 = 2000 - W1

Pauseus W2

Loop
I also loaded the first two data bytes with the command data 0, (135,0) at the start of the program to set a suitable initial position for the servo in case the driver board was looking for a value before the main board first sent it.

I presume that each time the loop is executed, the hserin reads the buffer and uses the value there, whether it is the same as last time or new.

I made a little test program that cycled the servo up and down through its range to test everything but the hserin part of the board. This appeared to work perfectly and no sign of servo jitter.

Obviously then I need the corresponding changes to the main board -

Servo data out from the hserout pinn not the previously selected pin

Remove the servo power supply and put it on the driver board.

The hserout pin (C.0) is also used during program load, but the circuit is built on a project board so I am using the jumper to change between programming and run modes.

With careful reading of the command instructions in section 2 I came up with the following -

In the init: routine -
Code:
Symbol n_servo = b18         ‘b18 as required servo position to be transmitted to the driver

Hsersetup B4800_4, %10010    ‘. Inverts serial output and disables hserin pin

‘And in the main routine -

Hserout 0, n_servo            ‘Inserted place of each servopos command previously used

                    ‘I assume the wake up command is not required(?)
Put it all together, and with the normal mix of trepidation and anticipation, tried it out.

Correct voltages at the chip pins, circuits carefully checked, but absolutely nothing. Not a single move or even jitter of the servo.

I have carefully checked both circuits many times and they seem correct, but as always, the only real check is when they work.

But I feel most likely is the programming for the hardware serial communication.

Did I miss something in my interpretation of Hippy’s code for the driver board?

Or did I get the sending side on the main board wrong. (I definitely checked the jumper position and achieved the download, then moved the jumper. )

So near yet so far!

Eng460
 

lbenson

Senior Member
hserin is non-blocking, and returns immediately whether or not a new byte has arrived.

For slow speed arrivals, something like this works.
Code:
do
  command = $FF ' non-valid command
  hserin command ' if no bytes ready, no change
  if command <> $FF then 
  ' ... ' do what you want with a new command
  endif
loop
Within the IF structure, SERTXD(#command," ") will show what you are receiving.

If you need high speed hserin, there's a pokesfr hack which allows up to 9600 baud to be glitch-free.
 
Last edited:

Eng460

Well-known member
Thanks Ibenson. Yes, I believe my application is definitely in the low speed requirements, at least slow speed in Picaxe terms, as it is not necessary to update a servo position very quickly, at least with my particular engine, so I don't expect to need the high speed solution.

I am wondering whether the problem at the moment is the unfamiliar hardware serial commands, (whether I have them right?) Or perhaps my base control algorithm. I will load a test program on to the main board, similar to the one I used for the driver board, to provide a known sequence of servo positions, but send them to the driver board over the serial link. This will clearly prove whether or not the problem is in the communications sequence.

I will come back when I have done that test. Funny thing, I seem busier than ever these days. I hope everyone is keeping well and safe.

Eng460
 

Eng460

Well-known member
Well I have been at this all week and feel that I am going backwards rather than forwards.

The code I posted last week does not work, (using hserout and pulsout to receive the value and position the servo) in that it gives quite erratic servo movements. I conclude that it is the hserin communications that are key to the problem, so I designed a circuit with two 08M2+ chips, with hserout on one (master) to hserin on the other (slave). I also connected the hserout of the slave to the hserin of the master, and constructed it on a breadboard.

I then wrote a short code to cycle through the range of servo pulse lengths that I wanted (135 - 200) up then down and loop. It included an LED to indicate when a value was sent, and to give two short flashes if the same one was received back, and also a sertxd command in each loop to tell me what data was returned by the slave.

Code:
Init:

Pause 500

Symbol swbutton =C.3

Symbol led= C.2

High LED

Pause 1000

Low LED

Hsersetup B4800_4, %10

Hserout 0, (0,0)        ‘This ensures 0 in both bytes of the slave fifo buffer to start.

B0=0

Main:

Do

For b0= 135 to 200        ‘Start a count up

    B6=b0

    High LED

    Pause 250

    Hserout 0, (b6,b6)        ‘This should put the same value of b6 into each of the two    
                         ‘byte positions in the slave buffer

Low LED

Hserin b8

If b8 = b6

    High LED

Pause 250

Low LED

Pause 250

High LED

Pause 250

Low LED

Endif 

Pause 250

Next b0

For b0 =  200 downto 135 step 1

B6=b0

High LED

Pause 250

Hserout 0, (b6,b6)        ‘This should put the same value of b6 into each of the two byte    
                     ‘positions in the slave buffer

Low LED

Hserin b8

If b8 = b6

    High LED

Pause 250

Low LED

Pause 250

High LED

Pause 250

Low LED

Endif 

Pause 250

Next b0

Sertxd (b8)

Loop
Then I put the corresponding code in the slave, to read the buffer, send the pulsout, calculate and pauseus the rather required remainder of the servo pulse frequency (20 mS) plus I added the hserout to reflect back to the master the received pulse. I believe the hserin only receives one byte at a time, but the code example is section 2 uses “hserin w1” I don’t know if it matters, I actually also tried both hserin b2. I assume that because this routine cycles much faster than the master routine that hserin executes several times before a new value is received so presumably, one way or another picks up both bytes. (Both show in the terminal display).

I hoped that by reflecting back what was received I would be able to see by via sertxd and the terminal emulation if any bytes were missed. Here is the slave code -

Code:
Init:

Pause 750

Symbol LED=C.2            ‘led inserted until circuit tested than C.2 connected to the                             ‘servo data pin.

Pause 750

Hsersetup B4800_4, %10

W2 =0

Main:

Do

Hserin w1

W2 = w1

W5 =2000 - w1

Pauseus w5

Pulsout LED, w2

Pauseus 1000

Hserout 0, w1

Loop
In the slave routine, I also tried pauseus 2000 - w2, then the hserout, but it made no difference.

The result, the terminal displayed the expected sequence of numbers, each one appearing twice with none missing. However, the master LED did not give the two short flashes, indicating that the returned values were not in sync with the sent values, but as there were none missing, I am happy with that.

So what is wrong?

Well, the brief led flashes on the slave were difficult to interpret, but when I substituted the servo, it alternated between two positions only.

I added a sertxd to the end of the slave routine, before the loop statement. The terminal displayed a sequence of byte values that bore no relation to what was sent or returned and most were of a value below the minimum servo pulse of 75. I fear this might have even damaged the servo.

I apologise for the long tale, but I am at my wits end, and would really appreciate some help in understanding how to solve the problem.

Everything works when tested individually, proving the circuit and so on, but together? Still a mystery.

Eng460
 

hippy

Technical Support
Staff member
So what is wrong?
You are executing "HSerIn w1" without taking into consideration whether any data has been received or not. See lbenson's Post #10 and/or my post #3 - My Post #3 should work 'as is'.

Forget receiving data and echoing it back; that adds its own complications, is only likely to have you thinking it's not working once it is.
 

Eng460

Well-known member
Hi Hippy, I clearly did not understand the subtlety of these steps in the program.

Still early morning here, but I will try that later today, Thank you.

Eng460
 

Eng460

Well-known member
Hi Hippy,

Programmed the slave exactly per your code.

Got an error “command not supported by the chip on the mode parameter of the hsersetup command” - it referred to bit 2. So I modified the mode qualifier to %10 ( instead of %110). It then compiled and downloaded ok, so seemed promising.

Good news is that the servo showed some life, but only alternated between two positions, so not great progress.

I then cut down the master chip program as follows to try and compliment your slave program.

Code:
Pause 500

Symbol led= C.2

High LED

Pause 1000

Low LED

Hsersetup B4800_4, %10

W3=75                ‘Show servo movement before starting up-down routine

Hserout 0, (w3)

Pause1000

W3=200

Hserout 0, (w3)

Pause 1000

Main:

Do

For b0= 135 to 200 step 2        ‘Start a count up

    High LED

    Pause 250

    Hserout 0, (w0)

    low LED

    pause 500

    Low LED

Next  b0

    Pause 500

For b0=200 downto 135 step 4

    High LED

    Pause 250

    Hserout 0, (w0)

    low LED

    pause 1000

Next  b0

Loop
No servo movement at all on this one.

I suspect I still do not have the commands correct, the mode parameter in hsersetup, or the break call in the hserout perhaps. Or even the mode in the slave.

Could you please comment on the requirements for the sending side of the program.

Eng460
 

hippy

Technical Support
Staff member
I had forgotten the HSERSETUP needed changing for the receiver as the 08M2 cannot invert its input.

There is no need to use HSEROUT to send from the master controller; a normal SEROUT can be used. This should command the servo controller to move the servo back and forth -
Code:
#Picaxe 08M2

Symbol SERVO_PIN  = C.0
Symbol SERVO_BAUD = T4800_4

Symbol LED        = C.2

PowerOnReset:
  High SERVO_PIN

MainLoop:
  Do
    Toggle LED
    For b0 = 175 To 225
      SerOut SERVO_PIN, SERVO_BAUD, (b0)
      Pause 50
    Next
    Toggle LED
    For b0 = 225 To 175 Step -1
      SerOut SERVO_PIN, SERVO_BAUD, (b0)
      Pause 50
    Next
  Loop
 

Eng460

Well-known member
Thanks Hippy, will try that later today and report back.

(I have learned to copy it exactly now.)

I assume that using the serout command, it does not have to be on the hserout pin. That would avoid programming causing spurious outputs that occur with the hserout pin.

Eng460
 

Eng460

Well-known member
Hi Hippy,

Copied that code including pin allocations, board connections do correspond.

No servo movements still, unfortunately.

Is the program for the slave still appropriate (using hserin) or does that have to be changed to work with the serout?
I still have your first code from post 3 programmed on the slave.

That PowerOnReset lable puzzles me. Should a "low" follow? Or does the serout just take over from the high?

Just to see what happened, I opened the Serial terminal while that program was running. The receive buffer rapidly with filled with numbers like the following:

004 000 017 000 008 000 016 000
000 015 000 015 000 000 016 000
008 000 017 000 004 000 018 000
009 000 019 000 002 000 020 000
010 000 021 000 005 000 022 000
011 000 023 000 001 000 024 000
012 000 025 000 006 000 026 000

Every second one is 000, the highest number I saw in the alternate bytes was 42, but obviously not the answer to the big question.

I don't know if that is of any use or just irrelevant.

Eng460
 

lbenson

Senior Member
Please show your code, every time, so we can see how the output program and input program correlate with the sertxd output that you are seeing.
 

Eng460

Well-known member
Thanks Ibenson for that suggestion, I think that is part of my problem also - I am never quite sure what I am supposed to have at the other end of the link.

Your prompt was especially valuable, as I decided to just make sure that I had both chips programmed with the current program before posting. And sure enough, I noticed that the wrong tab was open in the editor, so I programmed both again, just to be sure.

Good news - the servo is now smoothly moving from end to end as it should, changing direction as the LED toggles. So the communications seem to now be sorted using the serout command on the master as below.

There is an occasional unexpected flick to the 75 position, which is not so good, but as my test batteries are getting a bit low, it is possible that one of the chips is restarting despite my having separate battery packs for the Picaxe chips and servo. I will explore that issue a bit more tomorrow with a better power supply, and perhaps a long blink of the led or other indicator of a restart.

As requested here is the current code in the master, then the slave/servo driver chip for any final comments. It might also help anyone wanting to try the separate servo driver arrangement. I will also now be able to get back to using my main program to determine the engine speed.

Code:
;Master

#No_data
#Picaxe 08M2
Pause 800
Symbol SERVO_PIN  = C.0
Symbol SERVO_BAUD = T4800_4
Symbol LED        = C.2

PowerOnReset:
  High SERVO_PIN

MainLoop:
Do
Toggle LED
For b0 = 175 To 225
Serout SERVO_PIN, SERVO_BAUD, (b0)
Pause 50
Next

Toggle LED
For b0 = 225 To 175 Step -1
Serout SERVO_PIN, SERVO_BAUD, (b0)
Pause 50
Next

  Loop
And here is the code for the Slave/servodriver chip

Code:
;Slave   (47 bytes)

#no_data
Pause 700

Symbol servo_output = c.2         'servo data connected to this pin

PowerOnReset:
Hsersetup B4800_4, %10

MainLoop:

Do
Gosub ReadServoPosition

Gosub Setservo
Loop


ReadServoPosition:
b1=1
Hserin w0
If b1=0 Then
w1=b0
Endif

Return

Setservo:
Pulsout servo_output, w1

w2=2000-w1
Pauseus w2

Return

;end of slave program
Is there any way to recover a file name or other identifier from the programmed chip to help me avoid such an error in the future. I was so sure I had a system, but it let me down. My apologies, it is most embarrassing!

Eng460
 

lbenson

Senior Member
I would recommend that you move GOSUB SetServo within the IF statement in ReadServoPosition, so that you only execute SetServo when you have received a new value, not with every single pass of tight loop which will execute hundreds if not thousands of times a second.

Also it will help to see if the program is resetting if you put something like "SERTXD("Starting Servo Program",cr,lf) after PowerOnReset in both master and slave. Note that you can run multiple instances of PE6 so you can see what is happening with SERTXD in both programs (if you have more than one serial or usb/serial port and multiple programming cables--almost necessary when you are trying to debug two interacting picaxes).

(But glad you have made progress.)
 
Last edited:

Hemi345

Senior Member
I put the following near the top of every program I write. I've also started using Git to manage versioning. I'll put the last 6 characters of the SHA after doing a commit.

Code:
pause 1000
sertxd (13,10,"Program: ",ppp_filename,13,10)
sertxd ("Author: Hemi345",13,10)
sertxd ("Downloaded: ",ppp_date," ",ppp_time,13,10)
sertxd ("Git: c170f1",13,10)
After programming the PICAXE, I find myself trying to improve the code, then lose interest or get busy with something else and never finish it or upload the new version to the PICAXE. Then months/Years later, I decide I need to make a small tweak to the code currently "in production" and have no idea what's actually being used on the PICAXE. By including the SHA, I reset the PICAXE, make note of the Git SHA it says it's using and then make sure that the code I'm tweaking is what is currently running on the PICAXE. After making my changes, recommit it to the repo, update the SHA and be good for another few months or years :)
 

hippy

Technical Support
Staff member
I would recommend that you move GOSUB SetServo within the IF statement in ReadServoPosition, so that you only execute SetServo when you have received a new value, not with every single pass of tight loop which will execute hundreds if not thousands of times a second.
Calling SetServo every loop is essential to get the 20ms servo framing pulse regularly generated using PULSOUT and PAUSEUS :)

The 'w1' is the last valid data received, so setting that from 'b0' ( from HSERIN w0 ) is all that's required.

There is however no error checking on the incoming data so this would be better -
Code:
ReadServoPosition:
  b1=1
  Hserin w0
  If b1=0 Then
    If b0 >= 75 And b0 <= 225 Then
      w1 = b0
    End If
  Endif
  Return
As to the servo glitching to the 75 position; that could be the PICAXE resetting if the power supply is collapsing as the servo moves.
 

lbenson

Senior Member
Calling SetServo every loop is essential to get the 20ms servo framing pulse regularly generated using PULSOUT and PAUSEUS
That's not the case for me, at least for the servos I am using. Since 2009, my pan and tilt rivercam performs 2 pulsouts to set the servo only when there is a change in position. I did find that I had to do it twice to get it to stick:

Code:
      pulsout activeServo,activeSpot
      pause 20
      pulsout activeServo,activeSpot  ' twice seems to make it work
      pause 20
 

Eng460

Well-known member
Thanks Premelec and Hemi, I have given those suggestions a go in the code below. It sort of works, but the terminal displays ASCI numbers, not clear text with the statement I used. When doing the master program, it then continues on to display the serout bytes. This behaviour despite no hsersetup in the master routine. When the slave routine is defined, it only puts out 40 bytes, my count is 36, but close enough, but again ASCI numbers, not actual text, even though the sertxd statement is before the hsersetup command. Very Puzzling.

I know what you mean, Hemi about coming back some time later and wondering just which version was last programmed. Even better if I could get the terminal to display Clear Text.

Do I need a Hsersetup off or similar somewhere? It is almost like once issued, the Hsersetup stays in place even after power disconnected. Surely not.

Thanks Ibenson, the suggestion helps my understanding even if it is subsequently reversed. I see the matter is not quite resolved yet, but in the mean time, it is all working with Hippy's code, so I am feeling encouraged to continue again. Such constructive discussion is really helpful.

I use separate battery packs, one for the picaxe chips, and a separate one for the servo (with 0V connected) for testing. I must have used the batteries a lot yesterday as they have recovered a bit this morning and no glitches. I am happy that was just the power supply. For the complete project I have a board with a 9 V supply, two regulators, one for the servo, and the other with a diode and a larger capacitor on the inlet of the regulator for the picaxe chips. I think it worked until I added serout for the serial display, but I still had calculation algorithm issues so that will be confirmed one way or the other now I can get back to that aspect of the project. It seemed to be communications glitches rather than restarts.

Thanks Hippy, I have added that error checking line to my slave routine. Of course, that means that in case of an error, a pulsout is missed. Working so smoothly that I don't think there are any errors at the moment, but I am wondering.

I also used the code in AXE133 as a pattern to insert #define directives to make it easy to change between master and slave, while keeping the matching pair in one file. I hope this will help me avoid silly errors, or maybe just change the likely error. So far, it s working for me, much easier than commenting out #rem/#endrem statements

Here is the complete code as it stands, and working beautifully -

Code:
;Note you must comment out one of the following options to select required program
#Define Master
;#Define Slave
;Error checking of directives at end of program
;*****************************************************************************
#No_data
#Picaxe 08M2

#ifdef Master

Pause 800
#Define Show_Master_File_name

Symbol servo_pin  = C.0
Symbol servo_baud = T4800_4
#ifdef Show_Master_File_name
#Terminal 4800
Pause 1000

Sertxd ("Filename: ", Ppp_filename,13,10)

Pause 1000
#Terminal Off
#endif
Symbol led        = C.2
PowerOnReset:
  High servo_pin
MainLoop:
Do
Toggle led
For b0 = 175 To 225
Serout servo_pin, servo_baud, (b0)
Pause 50
Next
Toggle LED
For b0 = 225 To 175 Step -1
Serout SERVO_PIN, SERVO_BAUD, (b0)
Pause 50
Next
  Loop
#endif

;*********************************************************************************
#ifdef Slave

;Slave   (47 bytes)

Pause 700

#Define Show_Slave_File_name

Symbol servo_output = c.2   'servo data connected to this pin

  #ifdef Show_Slave_File_name
#Terminal 4800
Pause 1000

Sertxd ("Filename: ", Ppp_filename,13,10)

Pause 1000
#Terminal Off
  #endif

PowerOnReset:
Hsersetup B4800_4, %10

MainLoop:

Do
Gosub ReadServoPosition

Gosub Setservo
Loop


ReadServoPosition:
b1=1
Hserin w0 'w0 = b0:b1, w1 = b2:b3
If b1=0 Then
If b0>=75 And b0<=225 Then
w1=b0
Endif
Endif
Return

Setservo:
Pulsout servo_output,w1

w2=2000-w1
Pauseus w2

Return


;end of slave program
#endif
;**********************************************************************
;Directive error checking
#ifdef Master
#ifdef Slave
#Error "Oops - Both programmes selected"
#endif
#endif

#ifndef Master
#ifndef Slave
#Error "Oops - Neither programme selected"
#endif
#endif
so only wondering how to make the terminal display the file name in clear text, and back to the primary purpose of my project.

Thank you to everyone who has contributed to helping sort out the communications.

Eng460
 

lbenson

Senior Member
When I search for Ppp_filename, I find, other than this one, only threads started by Hemi345 or PieM. I never knew about this before.

How is this useful feature so little known (maybe Hemi345 and PieM are the only ones who actually read all the way through the PE6 manual).
 

lbenson

Senior Member
Regarding what you call "ASCII numbers", if you're referring to hex characters within brackets, like "[AF]", I think this is because you have servo_pin defined as C.0, which is the pin to which SERTXD goes, so whatever you send there, the serial terminal will try to interpret. Try changing it to "Symbol servo_pin = C.4" (and move the wire which is connected to the second 08M2).

To see what you're receiving, in the slave portion, after "If b0>=75 And b0<=225 Then", put "SERTXD(#b0," ").
 

hippy

Technical Support
Staff member
I also used the code in AXE133 as a pattern to insert #define directives to make it easy to change between master and slave, while keeping the matching pair in one file.
That may actually prove more trouble than it's worth long term. Once the servo driver is working you shouldn't have to ever touch it again so it just becomes clutter to keep it in the single file. I find it's easier to have "Master-003.bas" and "Slave-001.bas" files with the number incrementing for the latest saved version.
 

Hemi345

Senior Member
I find it's easier to have "Master-003.bas" and "Slave-001.bas" files with the number incrementing for the latest saved version.
Numbering the filenames with version info is OK if you're not using includes (.basinc) but it quickly becomes a pain if you write programs like I do where it's an iterative process of writing a small program, getting that thing to work, then incorporating it into the main program. It's handy to use an included file to define your variables and initial setup and include it into the main program and any test programs you might write. But if the included filename keeps changing with version info, it's a pain because all programs that reference that include must now be updated to point to the new filename. This is where Git really helps out. I'm talking about the local version of Git, not Github. Years ago, I watched Lynda.com training videos for learning Git by Kevin Skoglund (which are fantastic) and I've been a fan of using it ever since.

You make some changes to your program, then "commit" the changes with a simple command including a short comment of what you changed (if you're programming PICAXE using VSCode, Git is built in to the UI!). If you're program doesn't work as expected, you can revert your changes to the last commit (or any previous commit).

Sorry to get off topic. I should make a post in the PICAXE Editor section of the forum encouraging the developers to build in some basic Git functionality, that would be awesome.
 

Eng460

Well-known member
Hi Ibenson, you can add me to the list of people who actually read the instruction manuals. It is even one of those family jokes that my children enjoy at my expense. So I know about those processor directives and the associated directives. I had remembered the ppp_filename variable, wondered how I could use it, but then did not think of using sertxd to read it, possibly because most of my projects don't have a display and are intended to be used without the computer connection after the initial programming. Well, that's my excuse anyway. And now I have done it as suggested, I am not getting the hoped for clear text result. I guess it is either so clear that no one ever thought of starting a thread, or so obscure that few ever could see its use! But I am very glad it is there, it would be impossible to find if not documented.

I am not getting hex numbers, simply groups of three decimal digits, ranging from 000 to 042, with none of the alphabetic characters you would expect if they were hex numbers. The use of C.0 comes from the first approach to driving a slave servo driver, using hserout, which is only available on C.0 (on the 08M2+ anyway). I could try C.4, as that is available at the moment and still leave C.0 for the servo pulse length. Terminal seems to pick up everything.

I found it interesting that serout on C.0 of the master seems to be working well with hserin at the other end of the wire on the slave (C.1 for hserin). but I will follow up the suggestion of using the #symbol on the slave. Should have thought of that too, but again reading the manual gets me into trouble as it states that hserin operates very fast and cannot handle changing from raw to ASCI on the fly. I may have misunderstood that too.

I have also found it confusing that the manual talks about the hserin/out commands only send one byte at a time and have to be executed more times to receive words. Yet all the examples use word variables, eg hserin W1, perhaps the command itself always retrieves the byte from each of the two bytes in that FIFO register, wherever that is. (I tried including some data to put a suitable initial value in each of those two bytes, but they do not seem to be the first two data locations.)

Hi Hippy, you may well be right about the #define routine not being worthwhile, but I next intend to move onto development of the master code to do the function my project requires, so plenty more revisions. I am hoping it might be helpful to keep the correct slave code with the master code, as even with the error checking routine it is only about 60 short lines at the end of a relatively short program. It is a tossup what will work best for me when I want to repeat the project in a year or more, which I expect might happen if I can get it all to work. Only time will tell.

Thanks, Hemi, keeping up with revision control is certainly quite a problem in any field. But I don't think I am ready for a new way to do it. I do have a sort of system, even if I make the odd embarrassing error. But a separate thread on the topic is a good idea. It might be hard to find if buried deep in this one, and many could find it helpful.

By the way, I am another who was introduced to Picaxe by Stan's articles in Silicon chip many years ago. I noticed these referred to in another thread quite recently.

Eng460
 

lbenson

Senior Member
Yet all the [hserin] examples use word variables, eg hserin W1, perhaps the command itself always retrieves the byte from each of the two bytes in that FIFO register, wherever that is.
My code for HSERIN in post 10 uses only one byte, after setting, for example, b0 equal to $ff, a value I expect never to receive. Hippy's superior code reads into a word (w0) after setting b1 to a non-zero value. This will be set to zero only if the hardware serial has received a byte, the value of which will be placed in b0. Therefore you test for b1 equal to zero to see if you have actually received a byte.

This is equivalent to my testing for b0 not equal to $ff, with the added ability of HSERIN to receive an actual $ff.

There is no reason why HSERIN cannot be used to receive serial output sent by SEROUT. HSERIN is able to receive serial input at a much higher baud rate than SEROUT is able to send, and it is non-blocking, unlike SERIN--but one byte at a time with, on the M2s, only a 2-byte buffer, so your program must be quick to retrieve received bytes, or the buffer will be overrun and bytes will be lost.
 
Last edited:

hippy

Technical Support
Staff member
I am not getting hex numbers, simply groups of three decimal digits, ranging from 000 to 042, with none of the alphabetic characters you would expect if they were hex numbers.
This is probably a result of having the servo PICAXE connected to the C.0 pin of the controlling PICAXE.

HSEROUT and the SEROUT C.0 you are now using has to use the opposite polarity to what SERTXD produces because the receiving HSERIN input on the servo driver cannot be inverted on a 08M2.

If you move the outbound serial to the servo PICAXE from C.0 and put it on another pin that would probably resolve the issue and would be recommended anyway.
 

hippy

Technical Support
Staff member
This is my refined version of the software. The master has the control to the slave on pin C.1 rather than C.0. The slave is more resilient to data being sent more frequently than previously. Both report SERTXD details when they start. Both can use SERTXD while executing to aid debugging.
Code:
#Picaxe 08M2
#Terminal 4800
#No_Data

; MASTER software
;                  .------------------------.
;   .----_----.    |          .----_----.   |
;  -| +V   0V |-   |         -| +V   0V |-  |
;  -| SI   SO |-   |         -| SI   SO |-  |   _______
;  -| C.4 C.1 |----'         -| C.4 C.1 |<--'  |       |
;  -| C.3 C.2 |-===-|>|--.   -| C.3 C.2 |----->| SERVO |
;   `---------'     LED -^-   `---------'      |_______|
;      MASTER                    SLAVE

Symbol SERVO_OUT  = C.1
Symbol SERVO_BAUD = T4800_4

Symbol LED        = C.2

PowerOnReset:
  High SERVO_OUT
  Pause 2000
  SerTxd( "08M2 Master - ", ppp_datetime, CR, LF )
  
MainLoop:
  Do
    Toggle LED
    For b0 = 175 To 225
      SerOut SERVO_OUT, SERVO_BAUD, (b0)
      Pause 50
    Next
    Toggle LED
    For b0 = 225 To 175 Step -1
      SerOut SERVO_OUT, SERVO_BAUD, (b0)
      Pause 50
    Next
  Loop
Code:
#Picaxe 08M2
#Terminal 4800
#No_Data

; SLAVE software
;                  .------------------------.
;   .----_----.    |          .----_----.   |
;  -| +V   0V |-   |         -| +V   0V |-  |
;  -| SI   SO |-   |         -| SI   SO |-  |   _______
;  -| C.4 C.1 |----'         -| C.4 C.1 |<--'  |       |
;  -| C.3 C.2 |-===-|>|--.   -| C.3 C.2 |----->| SERVO |
;   `---------'     LED -^-   `---------'      |_______|
;      MASTER                    SLAVE

Symbol HSERIN_PIN  = C.1
Symbol HSERIN_BAUD = B4800_4

Symbol SERVO_PIN   = C.2

PowerOnReset:
  Pause 2000
  SerTxd( "08M2 Slave - ", ppp_datetime, CR, LF )
  ;                       RTRTB
  HSerSetup HSERIN_BAUD, %01000

MainLoop:
  Do
    Gosub Servo5msPeriod
    Gosub Dummy5msPeriod
    Gosub Dummy5msPeriod
    Gosub Dummy5msPeriod
  Loop

Servo5msPeriod:
  Gosub ReadServoPosition
  PulsOut SERVO_PIN, w1
  w2 = 500 - w1
  PauseUs w2
  Return

Dummy5msPeriod:
  Gosub ReadServoPosition
  PauseUs 500
  Return

ReadServoPosition:
  b1 = 1
  Hserin w0
  If b1 = 0 Then
    If b0 >= 75 And b0 <= 225 Then
      w1 = b0
    End If
  Endif
  Return
 

Eng460

Well-known member
Thank You so much Hippy for the effort you have put into this code. I have carefully saved that as my reference code for the communications and servo driver.

I suppose there is a subtle reason for dividing the gap between servo pulses into three blocks, but I have not been able to figure out why you have done that.

I think terminal is playing games with me. The first time I loaded that new code, I still got the groups of decimal numbers. I searched around the setting in terminal window, and found an option for Display RX data as ASCII. Ticked this and next start terminal displayed the required text. But only once, immediately after a download.

Powering off the chips and powering up after 10 seconds to start again, I got hex numbers in square brackets, and further starts nothing. The buttons at the right of the Terminal receive display are also puzzling. some change colour when clicked, some don't. I have DSR red, the other three green, but cant find what they are supposed to do. Is there any reference material on the terminal window?

However, I now have a working slave driver, with working code for the master so I will continue to develop my project. I should be able to report back in a few days as to how it goes.

Thank you

Eng460
 

hippy

Technical Support
Staff member
I suppose there is a subtle reason for dividing the gap between servo pulses into three blocks, but I have not been able to figure out why you have done that.
The de facto servo frame rate is a pulse every 20ms so having four 5ms periods gives that, and that also allows the HSERIN to be checked every 5 ms, once in each block. With a two byte buffer for HSERIN that means that data could be sent 2.5ms after the last without any data being lost, without any over-run occurring.

One doesn't have to do that but, reading far too often while not receiving anything, feels better than not having read often enough and missing something.

Four 5ms periods seemed a suitable and easy choice, knowing whatever the PULSOUT it would be less than 5ms.
 

Eng460

Well-known member
Thanks, Hippy. That makes sense. I will try it and let you know.

Hi Ibenson, It is always surprising how hard it can be to describe exactly what you are looking at to someone without it in front of them.

I had hoped there was a simple answer, but will come back to the serial terminal behaviour later when I can present the problem a little more clearly. I am still trying to understand the pattern, so I will keep observing, take a screen shot or at least save the Serial Terminal receive screen, and be back in a few days on that one. I am getting clear text of the file name, certainly after a download and I think mostly when I power up and start the already programmed chip. So that is the most important point for the moment. I get on better working on one issue at a time.

I will watch it closely as I do the necessary coding to get the primary function of the project working. There are still many hurdles to be crossed in transferring the communications procedure from the breadboard I have been using to the more permanent soldered printed circuit version.

Eng460
 

Eng460

Well-known member
Well, time to report some progress.

I experimented with going back to using serout on C.0, to control the servo driver. The problems with Serial Terminal were a distraction, and clearly not the main issue, using C.0 or C.1 both seem to work equally well.

So I turned back to my AXE 134 20 x 4 line display and brought over some code from my early efforts into Hippy’s refined code in post 34. This worked well and I was impatient to makes some progress, so turned off Serial Terminal, and concentrated on using the separate display.

I tried the ppp_file name as a first step. I found that my file names are way too long, and overflowed onto line 3, skipping line 2 as expected. I tried scrolling the window with some success, but no amount inserting the clear display (command 254,1) would reset the display after using the scrolling feature, to allow me to then proceed to display items in my chosen locations.

I have downloaded all the available data sheets but cannot find the more complete list of commands referred to on the AXE 134Y data sheet, so I only have the abbreviated list on that data sheet plus a few more from the LCD chapter in section 3. Does anyone have a link to the more complete list of commands?

I resorted to just displaying the date, (ppp_date_uk) which fitted in one line and worked well. As this is put in by the preprocessor, I assume it is the date program was downloaded and stays constant to help me identify the file later.

I really would like to just scroll that long file name on line 1 or even two lines, then clear the display after a pause, and continue with predictable display locations.

I then brought back in the code to measure the engine speed with pulsin, set point from read ADC, the algorithm to calculate the required new servo position, and to send it out to the servo driver board. All worked well. No more servo glitches, and when the servo is connected to the engine throttle valve, it all works well to control the speed. Only some final tuning of the control parameters required now to reduce oscillation in the control behaviour, which is expected for this type of system.

On the original thread title, I found in the end that while the 08M2+ can do each of the required functions, it could not do all at once. Pulsin, serout, servo pulses, and necessary pauses for processes to complete, all contributed to that hit or miss erratic behaviour.

In addition, long display messages led to servo glitches, but by deciding on screen locations, and not retransmitting data such as labels which do not change, the one chip handles pulsin, serout to the slave, reading ADC and updating three parameters on the display via serout without obvious issues. It was using “servo pos” that was the final straw.

The slave board with Hippy’s code now drives the servo without issue, but could be improved by my adding an LED to show it is alive in the initialisation, before the main loop starts. It is using the four equal pauseus steps as Hippy recommended.

I will get back to the issues with Serial Terminal at some future time in a separate thread, but for the moment, I want to get back to tuning that engine controller.

I am basically trying to do what a PID controller does, though realistically, it is a simple “proportional only“ controller, with a few modifications due to the way I have implemented it.

The code contains a few obsolete bits commented out, but when I have tidied that up, and have improved the tuning a bit, I can post it if anyone is interested.

Thank you to everyone who has helped me to get to this stage. It has been an unexpectedly long journey, and I have learned so much along the way from all of you.

Eng460
 

AllyCat

Senior Member
Hi,
I found that my file names are way too long, and overflowed onto line 3, skipping line 2 as expected.

..... cannot find the more complete list of commands referred to on the AXE 134Y data sheet, so I only have the abbreviated list on that data sheet plus a few more from the LCD chapter in section 3. Does anyone have a link to the more complete list of commands?
Yes, those displays are organised as (only) two lines, with line 3 an "extension" of line 1 (from character position 32 onwards) and line 4 an extension of line 2. So there are "gaps" of 12 characters in between the lines (with a 20 character display).

The additional commands are in the display (controller) data sheet, for example here . They are accessed via the AXE 133/134 firmware by prefixing them with the 254 control code. I think you can (horizontal) scroll by either advancing the line start address or allowing the cursor (entry point) to "auto scroll" the line. For an "automatic" scroll you will need to slow the period between characters being sent. Otherwise, a specific piece of program code (in your 08M2 or the AXE134 firmware) would need to increment the line start address at a suitable rate.

Cheers, Alan.
 
Top