SIMPLE communication between to 08M2 chips

FunFlyer

New Member
Hi Alan,

the logic analyzer is here. I took some samples. I wanted to attach the trace, but unfortunately PulseView doesn´t save the trace. When I select the save option, it just keeps saving...... So I took some screenshots. First one shows several databursts. I measured the period to be 21ms - as expected.

24626

second trace shows a complete data burst of 2.4ms - also no surprise.

24627

Then I thought, shouldn´t I be able to "manually decode the information, at least the header? Turns out I could´n´t. When I don´t touch any of the sticks on the transmiter, shouldn´t the channel indo be (almost) the same? I couldn´t find any repetition in the databurst. Even the beginning of each burst, where I was lokking for the header, is different in every dateburst. Am I doing something wrong? Like when I selected the wrong speed in the terminal window?

24628

regards

Herbert
 

AllyCat

Senior Member
Hi,

The first "error" I've noticed is that the sampling rate is (still) set to 100 kbit/sec but you're measuring serial data at 115 kbaud (~bits/sec) ! Also, one of the great advantages of a Logic Analyser (particularly attached to a PC) is that you have enormous storage capability (but don't go mad). Therefore, you should be using a sampling frequency of about 1 Mbits/sec and showing a few more channels. In particular, there is the "Automatic Decoders" button (just to the right of the bit rate) where the UART option (when configured correctly) will verify what's being recorded and shown.

Also note that you can set up a trigger to start the signal at the same time, which would probably have given a "stable" result - but still "wrong" because of the under-sampling.

Cheers, Alan.
 

FunFlyer

New Member
Hi Alan,

I think I made some progress on the analyzer. Here´s the latest I produced.

24632

The header is OK now, but the servo information still makes no sense to me at all. Since the sticks are all centered, I expected the values to be (almost) the same.

Now to the software. I integrated your sugesstions about resetting the pointers, and a "marker" to see when the cycle begins. Here´s the modified code:


MainLoop:
Do
Do
hSerPtr = 0
ptr = 0
GetByte(header)
Loop Until header = $A1 Or header = $A2
pulsout checks, 100

and I took out the pause at the buttom


; Pulsout PPM, rest_of_frame
; pauseus breaktime

and here´s what the scope shows


24636

thats seems to be OK in terms of stability, however the transmitter doesn´t recognize the signal. So I checked back with the reference signal

24635

the difference is, that before the first pulse and after the last pulse the signal is low, for what looks to me, is the same time we have between the pulses, and else the signal is high.

Do You think, that that could be the problem?

regards

Herbert
 

AllyCat

Senior Member
Hi,

That looks good to me. The "A1" is correct and then the data Words are sent "High Byte First", but "Low bit First" (PICaxe uses Low Byte First but the GetWord Macro should be sorting that out in the Program). Thus the first data Byte is %00000111 = $07 = 7 (* 256) and the Low Byte %11111111 = $FF = 255 so the Word value = 7 * 256 = 1792 + 255 = 2047 (or $07FF).

The second word has a Low Byte of $C5 = 12 * 16 + 5 = 197 which makes the full word = 1989 (or $07C5) that is just less than the expected "middle value" of 2047, half way up to the full-scale of 4095 (maximum 12-bit value). The third word starts with 08 (*256) = 2048, so is just at or above the middle point (depending on the next byte). Those values may then need to be scaled down (hint: the ** operator is often the best way to do this) and the "minimum" value added, to give a "normal" Servo pulse width range (e.g. 750 - 2250 us).

You also could have put the (servo) "pulse" waveforms onto the Logic Analyser, but the main "error" is that the PULSOUT instruction always creates a pulse from the present pin level, so you need a HIGH checks somewhere near to the top of the program. That should then give 7 negative-going pulses of variable widths, which I believe is your requirement?

Cheers, Alan.
 
Last edited:

FunFlyer

New Member
Hi Alan,

finially getting somewhere...

But first let me thank You for the explanation an the analyzer result. Finally it starts to makes sense!!!

right at the beginning of the program I added a

high PPM

before outputting the first pulse I added

low PPM
pauseus breaktime


Then come the seven pulses. After that


pauseus breaktime
high PPM


Here´s the result

24640

That´s recognized by the TX1 and I can control the motor and servo (somewhat). So I´m back to "scaling" the pulses.

I still haven´t come to grips with "**". So I went back to post #12, where I found the following line:


W6=W6-800**39322+640 '(New width=(Old Width-1msec)*0.6+0.8msecs)


I took the comment and came up with this:

Servo1=((Servo1-584)*0,6557)+960

584 is the SRXL Value for 1ms

960 is the Pulsout value for 0.6ms

0.6557 = (Pulsout for 1.8ms - Pulsout for 0.6ms) / (srxl for 2ms - srxl for 1ms)

0.6657 = (2880 - 960) / (3512 - 584)

Before outputting a servopuls I used to the following formula, considering PICAXE math going simply from left to right, and there are no decimals:

w1 = w1 -584 *655 /1000 + 960

in a spreadsheet the formula works fine, but not in the program. To get somewhere I used the srxl values without transformation, which gave the following results.

Picture 1: Channels 1 (ctr) and 2 (ctr) taken from the srxl stream, the rest of them are hardcoded CH3 = max, CH4 = min, CH5 ctr, CH6 =max, CH7 = ctr

24641

Picture 2: Channel 1 (min) the rest as in picture 1
24643

Picture 3: Channel 1 (max) the rest as in picture 1
24644

And as I said, I just can´t figure out the "**" operator. I found a post of Yours in another thread, where You explained it, in terms of "high" and "low byte", which helped a bit. In post #12 it says "W6=W6-800**39322" - where do You get the number "39322" from?

Looks like I´m going to need some (or even some more) help on that.

regards

Herbert
 

Attachments

AllyCat

Senior Member
Hi,
...... considering PICAXE math going simply from left to right, and there are no decimals:
w1 = w1 - 584 * 655 / 1000 + 960
in a spreadsheet the formula works fine, but not in the program.
The (PICaxe) "problem" with working left to right is that, supposing that w1 is 2048, then the subtraction yields 2048 - 584 = 1464 , but then 1464 * 655 yields a value (958920) which is too large to fit within a 16-bit word (maximum 65535). That's why PICaxe needs the "compound" operators such as "**" , but let's start with "//" which might be more familiar:

The // operator gives the "remainder" when dividing, for example 29 / 10 = 2 and 29 // 10 = 9 (or 29 - (2 * 10) = 9). Thus you could print out the result as 2.9 (or 2,9 in "Continental" notation). Then the */ operator is an instruction to perform a multiplication followed by a division: The numbers each side of the operator are multiplied together and then the result is divided by 256 . The reason for that is not (yet) "obvious" and it's only a PICaxe X2 operator, so let's move on to the ** operator, which multiplies the two numbers and then divides by 65536. The "clue" to those numbers is that 256 is the first number which is "too large" to fit into a single byte, and 65536 is the first number which is too large to fit into a word, i.e. 256 ** 256 = 1 (multiplied by 65536) and 256 * 256 = 0 (and 257 * 256 = 256 , etc.).

The ** operator gives the part of the result which is "too large" to fit into the normal (*) 16-bit word result, in a similar way to // giving the part which is "too small" when dividing (/) . Thus, the ** operator can be used to "build" a complete 32-bit (or "double-word") result (i.e. up to 4294967295), but here we can use it to scale accurate "fractional" values that are less than 1 (i.e. unity or 1.00000 decimal). In the example in the quote above, multiply 0,6557 by 65536 to give 42972 (with a pocket calculator or 'phone) and the equation becomes : w1 = w1 - 584 ** 42972 + 960 . Or with an X2 chip you could multiply the 0.6557 by 256 to give 168 and use : w1 = w1 - 584 */ 168 + 960 , but that is less accurate (and note that it is NOT dividing by 168 but multiplying by 168 and then dividing by 256).

There are also other ways to "spread out the calculation" so that intermediate values never get too large or too small, that might be necessary (for example if the "665 / 1000" were also a variable such as w2), but they are usually less accurate or difficult to find. And you might recognise that * 3142 / 1000 (Pi) could be replaced by * 22 / 7 (or occasionally / 7 * 22 ).

Cheers, Alan.
 
Last edited:

FunFlyer

New Member
Hi Alan,

Good news. It´s working!!!! I think I understand most of the "**" now. Here´s the final code:

Code:
; version histoty
; V0:    0riginal from Hippy taken from PICAXE forum
; V0.1: added additional segments
; V0.2: CRC commentd out
; V0.3: memory for rxCrc.lsb, rxCrc.msb and header corrected
; V0.4: scrapped unused code
; V0.5: Testroutine using "LED-blinkin" implemented, Terminal commented out
; V0.6: experiments with different timing values
; V0.7: translated everything to English, crc commented out
; V0.8: no output beginning loop modified, terminal on
; V0.9: clean out all uneccesary code
; V1.0: First production version installed on HAPPY HUNTER


#Picaxe 20X2
#No_Data
#No_Table

Symbol reserveW0 = w0  ; b1:b0
Symbol servo1    = w1  ; b3:b2
Symbol servo2    = w2  ; b5:b4
Symbol servo3    = w3  ; b7:b6
Symbol servo4    = w4  ; b9:b8
Symbol servo5    = w5  ; b11:b10
Symbol servo6    = w6  ; b13:b12
Symbol servo7    = w7  ; b15:b14
Symbol servo8    = w8  ; b17:b16
Symbol servo9    = w9  ; b19:b18
Symbol servo10   = w10 ; b21:b20
Symbol servo11   = w11 ; b23:b22
Symbol servo12   = w12 ; b25:b24
Symbol servo13   = w13 ; b27:b26
Symbol servo14   = w14 ; b29:b28
Symbol servo15   = w15 ; b31:b30
Symbol servo16   = w16 ; b33:b32
Symbol header    = b41

Symbol PPM              = C.2            `port assignment for PPM signal (the pulsetrain)
Symbol breaktime         = 180            `breaktime between pulses (0.4ms)
Symbol min_pulse        = 960            ;0.6ms
Symbol center_pulse    = 1920        ;1.2ms
Symbol max_pulse        = 2880        ;1.8ms



#Macro GetByte(bVar)
  Do : Loop While ptr = hSerPtr
  bVar = @ptrInc
#EndMacro

#Macro GetWord(wVar)
  Do : Loop While ptr = hSerPtr
  wVar = @ptrInc
  Do : Loop While ptr = hSerPtr
  wVar = wVar << 8 | @ptrInc
#EndMacro


PowerOnReset:
  SetFreq M64
  HSerSetup B115200_64, %001

MainLoop:
  High PPM
  Do
    Do
    hSerPtr = 0
      ptr = 0 
      GetByte(header)
    Loop Until header = $A1 Or header = $A2

    GetWord(w1) ; Servo 1
    GetWord(w2)
    GetWord(w3)
    GetWord(w4)
    GetWord(w5)
    GetWord(w6)
    GetWord(w7)
    GetWord(w8)
    GetWord(w9)
    GetWord(w10)
    GetWord(w11)
    GetWord(w12)
    If header = $A2 Then
      GetWord(w13)
      GetWord(w14)
      GetWord(w15)
      GetWord(w16)
   End If

    low PPM
    pauseus breaktime
;    1. Impuls2 = CH2 = Servo
    Servo14 = Servo14 - 584 ** 42972 + 960    ;0.6557*65536 = 42972
    Pulsout PPM, Servo14
    pauseus breaktime
     
;    2. Impulse = CH3 = Motor
    Servo13 = Servo13 - 584 ** 42972 + 960
    Pulsout PPM, Servo13
    pauseus breaktime

    Pulsout PPM, max_pulse
    pauseus breaktime

    Pulsout PPM, min_pulse
    pauseus breaktime

    Pulsout PPM, center_pulse
    pauseus breaktime

    Pulsout PPM, max_pulse
    pauseus breaktime

    Pulsout PPM, center_pulse
    pauseus breaktime
 
    low PPM
    pauseus breaktime
    high PPM
  Loop
In post #35 You mentioned

Code:
Do
    hSerPtr = 0
      ptr = 0 
      GetByte(header)
    Loop Until header = $A1 Or header = $A2
"That's certainly not "ideal", but it might prove if we're on the right track. "

So do we have to work on that, or can´t we just leave it as it is?

Many thanks for all Your help so far. It was a pleasure to learn from You, and a steep learning curve for me!!! Now I know where to to turn for my next project, which is just around the corner.

Here´s a picture of the hardware installed on the ship.

24646

In the middle of the picture You see the MPX receiver. On the pedastal left above is the board I built with the 20X2 and the T1-transmitter standing upright. On the right end of the picture You can see part of the controller, which controls all the lighting on the ship. It´s a 20M2. Here´s a picture of it in total. I did that project about 3 years ago. I figured that one out completely on my own.

24647

regards

Herbert
 
Last edited:

AllyCat

Senior Member
Hi,
In post #35 You mentioned
Code:
Do
    hSerPtr = 0
      ptr = 0  
      GetByte(header)
    Loop Until header = $A1 Or header = $A2
"That's certainly not "ideal", but it might prove if we're on the right track. "

So do we have to work on that, or can´t we just leave it as it is?
Congratulations on getting the program and hardware working; you've done well to do all this in a "foreign" language. :)

First, a minor "correction", that you've been using [ICODE ] ("In-Line Code") tags but for the main program it's better to use simple [CODE ] [/CODE] tags to prevent the program "dominating" the discussion. Or sometimes [ CODE=RICH] [/CODE] is needed to make the "COLORS" display (but I prefer to avoid those).

I'm pleased that you remembered my comment in #35, because too often people write "It's working so the program is finished" when there is very little "evidence" (proof) that it's completely true or reliable. If yours was a "Mission Critical" design (for example an aircraft flight system) then I would definitely consider it "NOT Finished", but perhaps we can be more "relaxed" for a boat control system. However, it's difficult for me to predict whether there might be "issues" because I don't have the hardware, nor use X2 chips, nor have any practical experience with Model Radio Control systems. So I can only give a few "tips" on what I think you should do next:

My concern about the code I've quoted above is that it might Reset the hSerPtr immediately after the Background Receive moves it on to the next byte (but before it discovers that the pointer has changed), so I think it might be better if that line were moved up to above the DO (so that the program only Resets it a single time, before it starts to compare the pointers). Alternatively, the original "Circular Buffer" method might work correctly, now that we know that the code can complete all its tasks in the available time.

A problem is that the header (A1 or A2) is not a "unique" marker because it is also a "data" value; and more basically the UART "Start" bit is just an ordinary "0" bit. Therefore, errors can occur if the program loop starts to read data at the "wrong" time (i.e. in the middle of the data burst). The CRC is a very reliable way to confirm that the data is perfectly accurate, but we can't use it because it takes too long to calculate. However, we can do a "Sanity Check", not to guarantee that the data is perfect, but to "Reject" any data that is obviously wrong (i.e. "Stupid"). It can be done with the MIN and MAX operators, for example: Servo = Servo - 584 ** 42972 + 960 MIN 1000 MAX 2000 (values as appropriate) or if you check the raw (input) data then you could set a substitute value, e.g. IF Servo > 4095 THEN : Servo = 2048 : ENDIF (a minimum test is not required because a negative value "underflows" to a large positive number).

Another issue is what to do if an error is discovered, or if no data is received within a "timeout" period: For example you could send NO Data (i.e. no Pulses), or "safe" values (e.g. average-width pulses) or you might repeat the data from the previous time-frame (in which case you must have written the latest data into a different area of the memory/buffer, e.g. by using the Circular Buffer method). Any of those features could be added into the program, but it must be your decision whether they are necessary or worthwhile, or just add unnecessary complications. ;)

Finally, but slightly Off-Topic; With reference to my last paragraph in post #37, please can you and/or Julian tell me if the "Pin9" on your Logic Analyzers is marked CLK or ETH GND ? Most of the recent Photos show it as CLK, but even the one I purchased recently is still marked GND ETH. I'm just interested to know if it really is a "CLOCK" Input (or Output) in addition to the normal 8 channels?

Cheers, Alan.
 
Last edited:

julianE

Senior Member
Finally, but slightly Off-Topic; With reference to my last paragraph in post #37, please can you and/or Julian tell me if the "Pin9" on your Logic Analyzers is marked CLK or ETH ? Most of the recent Photos show it as CLK, but even the one I purchased recently is still marked ETH. I'm just interested to know if it really is a "CLOCK" Input (or Output) in addition to the normal 8 channels?

Cheers, Alan.
Hi Alan, my analyzer looks like this
24652
Nothing is labeled ETH or CLK.
all the best.
 

FunFlyer

New Member
Hi Alan,

I´ll work on the "improvements" later, since I´m tied up in a woodworking project right now. I´ll keep You informed.

This is what my logic analyzer looks like, except for the missing "Saleae" logo.

24653

regards

Herbert
 

AllyCat

Senior Member
Hi Julian and Herbert,

Thanks for your replies and my apologies that I tend to use the terms "GND" (Ground) and "ETH" (Earth) interchangeably, so I should have asked if Pin9/10 is marked as GND or "CLK". The difference is shown in your two reply photos above and I've now verified that the two pins marked GND on my Logic Analyzers are definitely connected together (i.e. zero ohms). @Herbert, do you have a multimeter and if so could you check the resistance between the two pins marked CLK and GND on your version? If it's not "zero" ohms, could you also check both polarities (i.e. with +/Red multimeter probe to CLK and then to GND) ?

Briefly remaining OT and probably only relevant to UK members : I'm not a fan of Amazon, but currently there are versions of these 24-MHz 8-Channel Logic Analysers available for (much) less than £10 and with no minimum order charge, by using the "FREE click and collect ..." option from an Amazon Pickup Location (i.e. with the "Free UK Delivery by Amazon" search box ticked). ;)

Cheers, Alan.
 

FunFlyer

New Member
Hi Alan,

I made up a little Table. The measuring range on the multimeter was set to 20MOhm

ConnectorProbeResistance
GND Black (-)
11MOhm - slowly increasing
CLK Red (+)
GNDRed (+)
8MOhm - slowly increasing
CLKBlack (-)

Regards

Herbert
 
Last edited:

AllyCat

Senior Member
Hi,

Thanks guys, so there definitely do appear to be two (or more*) different versions of that Logic Analyzer, with some recent version having an additional "CLK" (I/O signal) pin marked on the label. Unfortunately, I've ordered two recently, because their photographs showed the "CLK" pin label, but when they arrived, both pins were marked "GND" and connected to the adjacent GND pin. The first Analyzer was returned as "not as described", but the second was so ridiculously cheap (hardly the cost of the included cables) that I'll keep it as a "spare". :)

So the question remains : "What does the CLK pin do (if anything) ?". @Herbert (or anybody else): A difficult question, but have you seen any indication of a "CLK" signal in the Pulseview / Sigrok User-Interface or its Help file? I haven't found anything, but thought that it could be "Context Sensitive" (i.e. shown only if the feature is available). However, I see that Herbert's reports itself as a "Saleae Logic" (although there is no logo on the label) as does one of mine, but another reports itself as a "CWAV USBee AX" (see photos), still with two GND pins.

CWAV USBee AX.pngSaleae Logic.png

*ADDENDUM: Looking in more detail at my Analyzers and the photos, I see that some versions have a "CH0" (as did the original Saleae Analyzers/software, and it seems Pulseview) whilst others start at "CH1". And some have a LED marked "CH0" (or "CH1"), which makes me wonder how/where "CH8" is connected and/or if the "CLK" is actually an output (e.g. Trigger) signal?
_______

Finally, returning to the original project, it can be seen that the 115 kbaud bytes are transmitted with just a small inter-character gap, approximately equivalent to a "1.5 Stop bits" UART configuration. Which confirms the need to use HSERIN, very probably with the PICaxe X2's Background Receive mode.

Cheers, Alan.
 
Last edited:

FunFlyer

New Member
Hi Alan,

I couldn´t find any information on the CLK pin either, so I posted a request for information on the website, where I bought it.

Does Your last comment imply, that I have to use HSERIN, since it´s not in the programm now?

regards

Herbert
 

AllyCat

Senior Member
Hi,

Sorry, perhaps I should have used the term "Serial Hardware" (UART), which uses the input pin named "HSERIN" (primarily B.6 on a 20X2). No you don't need to use the HSERIN command, but you are using the Hardware, by virtue of the HSERSETUP command (in the "PowerOnReset:" routine) and HSerPtr variable in the "Background Receive" mode.

Cheers, Alan.
 
Top