Download

40X2 Program Notes

1. GetSwPos().
This 12-position rotary switch was inherited from the previous incarnation. It selects a massivly-overkill of contents of the 4 messages which are stored, and sets their transmit periods.
The parameters are stored in EEPROM and can be changed. Each message has two fields, which may be any of the nine measured. If the period is 0, then that message is not transmitted in that switch position.

2.ConvertAnalog()
Each of the analog inputs is converted during a portion of eleven loops. The number of samples which are accumulated depends on the engineering conversion factor, since it performs multiplication. At the end of the cycle the accumulated value is divided to complete conversion to engineering units, then converted to ASCII characters. The multiply and divide values are stored in EEPROM, as is the position of the decimal point.

3. XmitControl()
Since transmissions have a period in seconds, an interrupt driven by the one-Hz watch timer increments four counters, one per message. XmitControl responds to counting limits of these counters by calling Transmit(), which reads the field values for the two fields and assembles the message and calculates the two checksum characters. Then the message is sent to the transmitter module.

Declarations and Data

#rem

Standalone.bas        Digitizes the analog inputs from the Signal Conditioner,

The resulting ascii characters are transmitted in RF messages.

John Saunders 10/10/2021

The 40X2 has 56 bytes of named storage and 56-255 of unnamed storage and 0-1024 bytes of scratchpad.

The unnamed are accessed using PEEK and POKE and the scratchpad by GET and PUT

If the variable name is preceded by WORD then a word variable may be used (using 2 locations)

Both unnamed and scratchpad can be indirectly addressed , the unnamed with @bptr and scratchpad with @ptr

Both also use the suffix inc and dec

#endrem


#PICAXE 40X2

rem Analog Signal Conditioner channels

symbol Grn     = 11        'Scale 0 - 4V

symbol Yel     = 17        'Scale 0 - 4V

symbol BNC_L_V = 1        'Scale 0 - 4,40V, 1 meg         

symbol BNC_R_V = 0        'Scale 0 - 4,40V, 1 meg

symbol Bipolar = 8        'Scale -0.2 - + 0.2V 2.2 meg

symbol Diff_V  = 9        'Scale 0 - 4,40V, 400 K

symbol Temp    = 10        'Scale 1 mv/deg A

symbol D9P4    = 12        'Scale 0 - 4V


rem Analog ADC inputs

symbol Batt    = 18        'Scale 0 - 4V

symbol Sw      = 5


rem ADC external reference range

symbol PosRefVolt = 3

symbol NegRefVolt = 2


rem Range switch Inputs: 

symbol BNC_L_R = PinB.7        

symbol BNC_R_R = PinB.6

symbol Diff_R  = PinD.2


rem interrupt

symbol CLkInt  = PinC.3        '1 Hz clock pulse 3 milliChCycle


rem Serial output to transmitterr

symbol XmitPort = A.7


rem Pins on the D9s at the front of the Signal conditioner

symbol D9P3        = D.3        

symbol D9P2        = C.4


rem Pins on the D9s at the back of the ADC

symbol DTRP4    = PinC.0        'protected input    

symbol RTSP7      = PinC.2        'protected input

symbol ENP6        = C.1    

symbol DATAP8     = D.0    '         


rem Controls:

symbol DC_Out  = D.4

symbol AC_Out  = C.7

symbol DC_In   = PinD.6

symbol AC_In   = PinD.5


symbol BipolarZero         = 1990

symbol AnalogStartAddr         = 56        'In SRAM

symbol AnalogTableAddr      = 0

symbol TxBufStartAddr         = 16        'In the scratchpad

symbol MsgKey             = "y"

symbol MsgTableStartAddr    = 50

symbol MsgInterval        = 40        'Minimum gap between messages


'EEPROM

'Analog parameter table, indexed by AnalogIndex * 5

rem      ADC       Mult   Div   DP   Marker

DATA  0,(BNC_R_V,   8,     2,    3 , "R")        'AnalogIndex = 0, Adjust DPLoc for range

DATA  5,(BNC_L_V,   8,     2,    3 , "L")        'AnalogIndex = 1, Adjust DPLoc for range

DATA 10,(Diff_V,    8,     2,    3,  "D")        'AnalogIndex = 2, Adjust DPLoc for range

DATA 15,(Grn,       8,     2,    3,  "G")        'AnalogIndex = 3

DATA 20,(Yel,       8,     2,    3,  "Y")        'AnalogIndex = 4

DATA 25,(D9P4,      8,     2,    3,  "E")        'AnalogIndex = 5

DATA 30,(Batt,      8,     2,    3,  "B")        'AnalogIndex = 6

DATA 35,(Bipolar,   8,     2,    1,  "C")        'AnalogIndex = 7,Allow for negative, use lower case symbol

DATA 40,(Temp,      9,     5,    1,  "T")        'AnalogIndex = 8,also * 4 then subtract 2079


rem Preset Message table of AnalogIndex of 2 fields per message, plus period in seconds

rem Rows are indexed bt swPos * 12


symbol TxDataStartAddr = 50


rem        Msg 0    Msg 1       Msg 2       Msg 3

DATA 50 ,(1,4,20 ,    3,0,0,    2,7,0,    6,8,120)    'Switch position A = 0

DATA 62 ,(1,4,40 ,    3,0,0,    2,7,0,    6,8,120)    'Switch position B = 1

DATA 74 ,(1,4,60 ,    3,0,0,    2,7,0,    6,8,120)    'Switch position C = 2

DATA 86 ,(0,3,20 ,    3,0,0,    2,7,0,    6,8,120)    'Switch position D = 3

DATA 98 ,(0,3,40 ,    3,0,0,    2,7,0,    6,8,120)    'Switch position E = 4

DATA 110,(0,3,60 ,    3,0,0,    2,7,0,    6,8,120)    'Switch position F = 5

DATA 122,(1,4,60 ,    0,3,64,    2,7,0,    6,8,120)    'Switch position G = 6

DATA 134,(2,7,40 ,    5,4,44,    2,7,0,    6,8,200)    'Switch position H = 7

DATA 146,(4,1,30 ,    3,0,34,    2,7,38,    6,5,200)    'Switch position J = 8

DATA 158,(4,1,60 ,    3,0,63,    2,7,66,    6,8,200)    'Switch position X = 9

DATA 170,(4,1,120,    3,0,163,    2,7,177,    6,5,200)    'Switch position Y = 10

DATA 182,(4,1,240,    3,0,243,    2,7,247,    6,8,250)    'Switch position Z = 11


'Variables:

symbol Msg0En    = bit0

symbol Msg1En     = bit1

symbol Msg2En  = bit2

symbol Msg3En   = bit3

symbol IntFlag     = bit4

symbol SendFlag    = bit5

symbol ReadyFlag   = bit6


rem Dedicated variables

symbol ChCycle  = b2    '0-9 Main count

symbol AnalogIndex    = b3    '0-8 

symbol MsgIndex    = b4

symbol SwPos    = b5    '0-11 Switch position

symbol OldSwPos = b6

symbol Duration = b7    'The minimum number of ChCycle between transmissions

symbol Msg0Count = b8

symbol Msg1Count = b9

symbol Msg2Count = b10

symbol Msg3Count = b11

symbol Msg0Period = b12

symbol Msg1Period = b13

symbol Msg2Period = b14

symbol Msg3Period = b15


'Reusable - 

symbol Scratch    = b20

symbol DecData    = b21

symbol Channel    = b22

symbol Marker    = b23

symbol Multiply    = b24

symbol Divide    = b25

symbol DPLoc    = b26    'number of decimal places

symbol ScratchAddr    = b27

symbol DataAddr    = b28

symbol Indx        = b29

symbol Iter        = b30

symbol Chardata    = b31

symbol CkSum    = b32

symbol AnalogVal      = w25

symbol AccumulatorVal   = w26

Setup and Main

Setup:

SETFREQ m8

LET DIRSA = %10010000

LET DIRSB = %00000000

LET DIRSC = %10010010

LET DIRSD = %00010001

LET ADCSETUP  = %0001111100101111    '2,3 for ext ref, 4 not present, ext ref on a.3, + and A,2 -

LET ADCSETUP2 = %0000000000000110    

LOW DC_Out

LOW AC_Out

LOW D9P2

LOW ENP6

LOW DATAP8

LET Msg0Count = 0

LET Msg0En    = 0

LET Msg1Count = 0

LET Msg1En    = 0

LET Msg2Count = 0

LET Msg2En    = 0

LET Msg3Count = 0

LET Msg3En    = 0

LET SendFlag = 0

LET ChCycle = 0

LET ReadyFlag = 0

SETINT  %00001000,%00001000,C    'Interrupt on 1 Hz clock


main:          

GOSUB GetSwPos            'Also sets the periods            

GOSUB ConvertAnalog

LET bptr = 8 * SwPos + AnalogStartAddr

INC ChCycle

IF ChCycle > 10 THEN    

    LET ChCycle = 0

ENDIF

GOSUB XmitControl

PAUSE 1

GOTO main

Sub-programs

GetSwPos:

READADC Sw,AnalogVal

FOR Scratch = 39 TO 231 STEP 16

    IF Scratch > AnalogVal THEN EXIT

NEXT

LET SwPos = Scratch/16 - 3    'Switch position 0-11

LET DataAddr = 12 * SwPos + TxDataStartAddr + 2

READ DataAddr,Msg0Period

LET DataAddr = 12 * SwPos + TxDataStartAddr + 5

READ DataAddr,Msg1Period

LET DataAddr = 12 * SwPos + TxDataStartAddr + 8

READ DataAddr,Msg2Period

LET DataAddr = 12 * SwPos + TxDataStartAddr + 11

READ DataAddr,Msg3Period

IF SwPos <> OldSwPos THEN

    LET Msg0Count = 0

    LET Msg1Count = 0

    LET Msg2Count = 0

    LET Msg3Count = 0

    LET ChCycle = 0    

ENDIF

LET OldSwPos = SwPos

RETURN


#rem

SRAM memory usage:

64 bytes starting at AnalogStartAddr to store analog values.

2 bytes store a the symbol in ASCII plus a comma, followed by

5 bytes of data converted to ASCII with decimal point.

Finally a comma


Scratchpad memory usage:

0-15 to store accumulated binary analog measurements 

20 bytes per message starting at TxBufStartAddr to store the current message being transmitted

#endrem


ConvertAnalog:

#rem

The processor has 8 active ADC ports.7 from The Signal Conditioner,plus the battery voltage

The output of this subprogram is measurements in engineering units.

Since Picaxe Basic does not do either floating point or negative values,

the ADC is designed to provide an exact 5 mv per count by designing the processor regulator to provide 5.12V

Measuring and displaying analog values therefore requires integer mathematics

including multiplication, division, and subtraction. These constants are provided in a table in EEPROM 

starting at.AnalogTableAddr, which has and is indexed by AnalogIndex and has 5 columns.

The values take into account the analog circuits, some with modifications.

#endrem


rem Zero the accumulators in scratchpad starting at 0 if LoopCount = 0

rem alse measure the 1.2V reference diode for ground loop correction


Rem Perform multiplication by measuring each analog multiple times and accumulate


FOR AnalogIndex = 0 TO 8                '9 analogs

    LET ScratchAddr = 2 * AnalogIndex        'Accumulators start at 0

    LET DataAddr = 5 * AnalogIndex + AnalogTableAddr

    READ DataAddr,Channel,Multiply,Divide,DPLoc, Marker

    IF ChCycle < Multiply THEN

        ADCCONFIG %0101

        READADC10 Channel,AnalogVal    

        GET ScratchAddr, WORD AccumulatorVal

        LET AnalogVal = AnalogVal + AccumulatorVal

        PUT ScratchAddr, WORD AnalogVal

    ENDIF 

    

    IF ChCycle = 10 THEN                             

        GET ScratchAddr, WORD AnalogVal

        LET AnalogVal = AnalogVal / Divide            'Do division

        

        IF Channel = Temp THEN                'Bipolar

            LET AnalogVal = 4* AnalogVal

            LET AnalogVal = AnalogVal - 4597    '273.15*18 - 320 Go figure!

            

        ENDIF    


        IF Channel = Bipolar THEN                    '200 mv input

            SERTXD(",200mv=") 

            IF AnalogVal >= BipolarZero THEN

                LET AnalogVal = AnalogVal - BipolarZero

                

            ELSE

            LET AnalogVal = BipolarZero - AnalogVal

                

                LET AnalogVal = AnalogVal | $8000        'Set MSB

                

            ENDIF

             

        ENDIF


        

rem Convert an analog binary to ASCII with decimal point in ordered location in RAM

rem Value to be converted is AnalogVal, Identified by AnalogID

rem Character for the decimal point is denoted by DpLoc

rem Inputs are in 


    

        IF AnalogVal > $7FFF THEN            'Minus

            LET Marker = Marker + $20

            LET AnalogVal = AnalogVal & $7FFF

        ENDIF    

    

        IF Channel = BNC_L_V AND BNC_L_R = 1 THEN        

            DEC DPLoc

        ENDIF

        IF Channel = BNC_R_V AND BNC_R_R = 1 THEN

            DEC DPLoc

        ENDIF    

        IF Channel = Diff_V AND Diff_R = 1 THEN

            DEC DPLoc

        ENDIF                '4 significant digits, plus decimal point and a comma

        LET bptr = 8 * AnalogIndex + AnalogStartAddr 

        LET @bptrinc = Marker

        LET @bptrinc = ","    

        LET DECData  = AnalogVal/1000        'Digit #1

        LET DECData  = DECData + "0"        'Ascii

        LET @bptrinc = DECData            'Digit 1 Pos

        IF DpLoc = 3 THEN

            LET @bptrinc = "."            'Digit 2 if period

        ENDIF

        LET AccumulatorVal  = AnalogVal//1000        'AccumulatorVal for digit #1

        LET DECData  = AccumulatorVal/100        

        LET DECData  = DECData + "0"        'Ascii

        LET @bptrinc = DECData                'Digit #2 w/o period else digit 3    

        IF DpLoc = 2 THEN

            LET @bptrinc = "."            'Digit 3 if period

        ENDIF        

        LET AnalogVal  = AccumulatorVal//100        'AccumulatorVal for digit #2

        LET DECData  = AnalogVal/10        

        LET DECData  = DECData + "0"        'Ascii

        LET @bptrinc = DECData                'Digit #3 w/o period else digit 4        

        IF DpLoc = 1 THEN

            LET @bptrinc = "."            'Digit 4 if period

        ENDIF

        LET DecData  = AnalogVal //10        'Least significant digit

        LET DecData  = DecData + "0"        'Ascii

        LET @bptrinc = DecData                'Digit #4 w/o period else digit 5

        IF DpLoc = 0 OR DpLoc > 3 THEN

            LET @bptrinc = " "            'Digit 5 if no period

        ENDIF 

    

        LET @bptrinc = ","                'Digit 6

        LET ScratchAddr = 2 * AnalogIndex        'Zero Accumulators which start at 0

        LET AccumulatorVal = 0

        PUT ScratchAddr, 0,0

    ENDIF

NEXT

RETURN


XmitControl:

IF Msg0En = 1 THEN

    LET MsgIndex = 0

    GOSUB Transmit

    LET Msg0En = 0

    RETURN

ENDIF

IF Msg1En = 1 THEN

    LET MsgIndex = 1

    GOSUB Transmit

    LET Msg1En = 0

    RETURN

ENDIF

IF Msg2En = 1 THEN

    LET MsgIndex = 2

    GOSUB Transmit

    LET Msg2En = 0

    RETURN

ENDIF

IF Msg3En = 1 THEN

    LET MsgIndex = 3

    GOSUB Transmit

    LET Msg3En = 0

ENDIF

RETURN


Transmit: 'Transmits the data in the message pointed to by MsgIndex (0-3)

rem The message starts with msgKey, a comma, Then 2 data values.(AnalogIndex 0-8) followed  by a checksum

rem The message is asembled in a buffer in the scratchpad starting at TxBufStartAddr

LET ptr = TxBufStartAddr

LET @ptrinc = MsgKey

LET @ptrinc = ","

LET @ptrinc = "K"

LET @ptrinc = ","

LET DataAddr = 12 * SwPos + TxDataStartAddr

LET DataAddr =  3 * MsgIndex +  DataAddr

READ  DataAddr,AnalogIndex 

LET bptr = 8 * AnalogIndex + AnalogStartAddr    'Where the data comes from

FOR Indx = 0 TO 7            'Transfer the selected analog data to the transmit buffer

    LET CharData = @bptrinc

    LET @ptrinc = CharData

NEXT

INC DataAddr

READ  DataAddr,AnalogIndex 

LET bptr = 8 * AnalogIndex + AnalogStartAddr    'Where the data comes from

FOR Indx = 0 TO 7            'Transfer the selected analog data to the transmit buffer

    LET CharData = @bptrinc

    LET @ptrinc = CharData    

NEXT

LET CkSum = 0

LET ptr = TxBufStartAddr + 4

FOR Iter = 0 to 14            'The last comma should not be included

    LET CkSum = CkSum + @ptrinc

NEXT

INC ptr                    

rem convert the checksum into hex

LET Scratch = Cksum / 16 + "0"

IF Scratch > "9" THEN

    LET Scratch = Scratch + 7

ENDIF

LET @ptrinc = Scratch

LET Cksum = Cksum & $0f + "0"

IF Cksum > "9" THEN

    LET Cksum = Cksum + 7

ENDIF

LET @ptrinc = Cksum

LET @ptrinc = 13

LET @ptrinc = 10

LET @ptrinc = 0

HIGH XmitPort

PAUSE 40

LOW XmitPort

PAUSE 20

SEROUT XmitPort,N2400_8,("14L1776")

LET ptr = TxBufStartAddr

DO UNTIL @ptr = 10

    SERTXD (@ptr)

    SEROUT XmitPort,N2400_8,(@ptrinc)

LOOP 

SEROUT XmitPort,N2400_8, (13,10)

SERTXD (13,10)

RETURN


interrupt:

IF Msg0Period > 0 THEN            '0 is inhibit

    INC Msg0Count

    IF Msg0Count >= Msg0Period THEN

        LET Msg0Count = 0

        lET Msg0En = 1

    ENDIF

ENDIF

IF Msg1Period > 0 THEN            '0 is inhibit

    INC Msg1Count

    IF Msg1Count >= Msg1Period THEN

        LET Msg1Count = 0

        lET Msg1En = 1

    ENDIF

ENDIF

IF Msg2Period > 0 THEN            '0 is inhibit

    INC Msg2Count

    IF Msg2Count >= Msg2Period THEN

        LET Msg2Count = 0

        lET Msg2En = 1

    ENDIF

ENDIF

IF Msg3Period > 0 THEN            '0 is inhibit

    INC Msg3Count

    IF Msg3Count >= Msg3Period THEN

        LET Msg3Count = 0

        lET Msg3En = 1

    ENDIF

ENDIF

SETINT  %00001000,%00001000,C

RETURN