Remote control by location (PIC in Oshonsoft) [Control section]

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Hi,
This is the control section of the project: https://forum.allaboutcircuits.com/...location-pic-in-oshonsoft.148795/post-1270205

I think that having a CONTROL SECTION to the project, will hopefully, save some confusion, if calculations and ideas are posted here instead of the main PBCs and programs for the peripherals etc.

This SERVO CONTROL CODE was kindly written by members of ETO, but I'm a bit stuck with a change to clock speed. It uses OSCCON which sets the OSC to 8mHz, where the main programs that this will be added into uses 8mHz Crystals X4 (PLL) so 32mHz.

I've been modifying it for testing, and I hope it is still ok. It moves the SERVOs incrementally, and once I;ve got this figured out, I can send it numbers to move the SERVOs instead.
Code:
'18F4431 8MHz XTL PCB9 REMOTE_SLAVE SERVO 8 020324 0903

Define CONFIG1L = 0x00
Define CONFIG1H = 0x06  '8mHz XTL x4 =32mHz
Define CONFIG2L = 0x0c
Define CONFIG2H = 0x20
Define CONFIG3L = 0x04
Define CONFIG3H = 0x80
Define CONFIG4L = 0x80  'Set for HVP
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40

Define CLOCK_FREQUENCY = 32
Define SINGLE_DECIMAL_PLACES = 2
Define STRING_MAX_LENGTH = 20

Define SIMULATION_WAITMS_VALUE = 1  'Comment in for SIM out for PIC

Dim wordTemp As Word
Dim ServoCount As Byte
Dim i As Word
Dim ServoPos(8) As Word
Dim servoDir(8) As Byte
Dim frame As Word
Dim rec As Byte
Dim pos As Word
'Dim dir As Byte

Symbol rled = PORTD.7

'OSCCON = %01110000  '& h70 8mHz XTL PLL
TRISA = %11000000  '7=OSC, 6=OSC,
TRISB = %00000000  '0=SEROUT
TRISC = %11110010  '6=1-slave4431_cs, 3=74HC164 MR, 2=74HC164 CLK, 0=74HC164 DATA'<<<<<<<<<<<<
'TRISC = %11111010  'CCP0 (RC2) & RC0 output'<<<<<<<<<<<<<<<<<<<<@
TRISD = %00000000
LATC.0 = 0  'ensure data is low
LATC.2 = 0  'and clock
LATC.3 = 1  'Master reset HIGH for run.'<<<<<<<<<<<<<<

'For i = 0 To 7
'LATC.2 = 1  'send positive clock edge
'ServoPos(i) = i * 250 + 2000  '1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps'
'LATC.2 = 0  'send negative edge
'servoDir(i) = i And 1  '<<<<<<<added
'Next i

'Start up led
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000

ServoCount = 8  'cause it to reset
T1CON = %00100000  'prescaler = 4
T1CON.0 = 1  'start timer
CCP1CON = %1000  'will go high on interrupt - will start a 0.5mS pulse
frame = 1000  'start everything in 4000 cycles

PIE1.CCP1IE = 1'Captrue compare for timer1
INTCON.GIE = 1'!!!!!!!!!!!


ServoPos(0) = 1000
ServoPos(1) = 1100
ServoPos(2) = 1200
ServoPos(3) = 1300
ServoPos(4) = 1400
ServoPos(5) = 1500
ServoPos(6) = 1600
ServoPos(7) = 1700

'ServoPos(0) = 1500
'ServoPos(1) = 1500
'ServoPos(2) = 1500
'ServoPos(3) = 1500
'ServoPos(4) = 1500
'ServoPos(5) = 1500
'ServoPos(6) = 1500
'ServoPos(7) = 1500

While 1  '\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

    While ServoCount = 0  'wait for 20mS to pass (=1/50th of a second)
    Wend
    While ServoCount <> 0
    Wend
    'Break'<<<<<<<<<<<<<<<<<<<<<
    For i = 0 To 7
    ServoPos(i) = ServoPos(i) + 1
        'dir = servoDir(i)  'doesn't matter if ISR happens as servoPos isn't changed by ISR
        pos = ServoPos(i)
        If pos < 2000 Then  'have we gone past the end?
            pos = 2000  'yes so make it the end stop
        Endif
        If pos > 4000 Then  'same for other end
            pos = 4000
            Endif
        INTCON.GIE = 0
        ServoPos(i) = pos
        INTCON.GIE = 1
    Next i

Wend

End

On High Interrupt  'go via location 0x0008
Save System

If PIR1.CCP1IF Then  'has CCP1 triggered?
    wordTemp.HB = CCPR1H  'get value of CCPR1 into wordTemp
    wordTemp.LB = CCPR1L
    If CCP1CON = 0x08 Then  'have we started the 1000 cycle pulse
        CCP1CON = 0x09  'yes so end the pulse after 0.5mS
        wordTemp = wordTemp + 1000  'adding 1000 will make pulse 0.5mS long
    Else
        LATC.0 = 0  'clear the data pin
        CCP1CON = 0x08  'No so output the timed gap
        If ServoCount < 8 Then
            'still doing the servos so add remainder of time
            wordTemp = wordTemp + ServoPos(ServoCount)
            wordTemp = wordTemp - 1000  'knock of the 1000 (0.5mS) already elapsed
            frame = frame - ServoPos(ServoCount)
            ServoCount = ServoCount + 1
        Else
            'done all the servos so just the frame gap to do
            wordTemp = wordTemp + frame
            frame = 39000  '40,000(20mS) minus time of positive pulse(0.5mS)
            ServoCount = 0  'start all over again
            LATC.0 = 1  'will become first pulse (is data pin of shift register)
        Endif
    Endif
        CCPR1H = wordTemp.HB  'put value back into CCPR1
        CCPR1L = wordTemp.LB
        PIR1.CCP1IF = 0  'clear interrupt flag
Endif

Resume
If anyone kows how to change this I would appreciate it.
C.
 
Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Hi,
I've written a program that controls 7 SERVO/MOTORS (only because I've used the 7th channel for timing) I only need 5XChannels.
I'll now have to test it a bit to make sure it's ok.
C
Code:
'18F4431 32MHz XTL PCB9 REM_SLAVE CHAN_CONT RE-DESIGNED 300324 1500
Define CONFIG1L = 0x00
Define CONFIG1H = 0x06  '8mHz XTL x4 =32mHz
Define CONFIG2L = 0x0c
Define CONFIG2H = 0x20
Define CONFIG3L = 0x04
Define CONFIG3H = 0x80
Define CONFIG4L = 0x80  'Set for HVP
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40

Define CLOCK_FREQUENCY = 32
Define SINGLE_DECIMAL_PLACES = 2
Define STRING_MAX_LENGTH = 20

'Define SIMULATION_WAITMS_VALUE = 1  'Comment in for SIM out for PIC

'Dim CHAN_Count As Byte
'CHAN_Count = 9 '8 cause it to reset
Dim chan_time(8) As Word 'Each Cnannel ON TIME
'FRAME = 20000us Not a VARIABLE
Dim frame As Word
frame = 20000
Dim frame_rem As Word 'FRAME_REM = FRAME-CHAN_TIMES.
Dim i As Byte 'chan_time sequence.
i = 0 'First CHANNEL
Symbol rled = PORTD.7

TRISA = %11000000  '7=OSC, 6=OSC,
TRISB = %00000000  '0=SEROUT
TRISC = %11110010  '6=1-slave4431_cs, 3=74HC164 MR, 2=74HC164 CLK, 0=74HC164 DATA'<<<<<<<<<<<<
TRISD = %00000000
LATC.0 = 0  'DATA inputs DSA+DSB Active HIGH Enables DATA entry (ensure data is low at start)
LATC.2 = 0  'CLK. Data is shifted on the LOW-to-HIGH transitions of the clock (CP) input.
LATC.3 = 1  '0= ALL BITS=0, 1= RUN

'Start up led
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000

'CHAN_Count = 9 '8 cause it to reset

T1CON = %00110001  '=All values are divided by PRESCALE=4.

INTCON.PEIE = 1  'PEIE/GIEL: Peripheral Interrupt Enable bit
INTCON.GIE = 1  'GIE/GIEH: Global Interrupt Enable bit
PIE1.CCP1IE = 1  'CCP1IE: CCP1 CAPTURE COMPARE for timer1 Interrupt Enable bit
'PIR1.CCP1IF '1= A TMR1 register capture occurred (must be cleared in software)
'PIR1.TMR1IF '1=TMR1 register overflowed (must be cleared in software)

CCP1CON = %00001000  'will go high on interrupt

chan_time = 0

main: '\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
Toggle rled
WaitMs 1000

chan_time(0) = 1000 '00000011 11101000
chan_time(1) = 1200
chan_time(2) = 1300
chan_time(3) = 1400
chan_time(4) = 1500
chan_time(5) = 2000
chan_time(6) = 2000 '^ TOT 10400
chan_time(7) = (20000 - (chan_time(0)+chan_time(1)+chan_time(2)+chan_time(3)+chan_time(4)+chan_time(5)+chan_time(6)))
'Analyser shows 9600 as Chan_time(7)
'2000-10400 = 9600

Goto main

End

On High Interrupt  'go via location 0x0008
Save System

If PIR1.CCP1IF Then  ''1 = A TMR1 register capture occurred (must be cleared in software)
    CCPR1H = chan_time(i).HB
    CCPR1L = chan_time(i).LB
    TMR1H = %00000000
    TMR1L = %00000000
    If i = 0 Then LATC.0 = 0
        i = i + 1
        If i >= 8 Then
        i = 0
        LATC.0 = 1
    Endif
    CCP1CON = %00000000 'Clear CCP1 PIN RC2'
    CCP1CON = %00001000  'Will go high on interrupt
    PIR1.CCP1IF = 0 '1 = (clear in software)
Endif
Resume
 
Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Hi,
REMOTE_SLAVE PIC:
I can now move a SERVO/MOTOR, 'say' CHAN _1, by inputting a number between 1000 and 2000.

The BASE is transmitting DATA to the REMOTE, and the REMOTE is receiving them.
The first 3BYTEs are for controlling CHAN_1, 'say' 0x53,0x53,0x53 or 555.
The range of the input is 'say' 200 and 900, so this must be converted to between 1000 and 2000.

I have the formula:
'say' (555 - 200)/7x10+1000 This is somewhere near 1500 which is 1/2 way.

My question is: how do I write OSHONSOFT BASIC to convert 3xBYTES into a WORD to carry this out, please.

(I hope you can understand ok)
Camerart
 

sagor

Joined Mar 10, 2019
908
Is it hex 53 or decimal 53? Hex 053 is a capital "S", whereas a decimal 53 is the ASCII "5", which makes more sense.
Sending "555" in ASCII can be converted to a binary by converting each ASCII string to a numeric value, with a function such as StrValW or StrValL
Or, take each byte value and multiply it by the position in the byte array, so first "0x53" (if that is what it is) is converted to a binary "5" and then multiplied by 100. The next is converted to a number and multiplied by 10 and final is just converted. Add them up for a final total.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Is it hex 53 or decimal 53? Hex 053 is a capital "S", whereas a decimal 53 is the ASCII "5", which makes more sense.
Sending "555" in ASCII can be converted to a binary by converting each ASCII string to a numeric value, with a function such as StrValW or StrValL
Or, take each byte value and multiply it by the position in the byte array, so first "0x53" (if that is what it is) is converted to a binary "5" and then multiplied by 100. The next is converted to a number and multiplied by 10 and final is just converted. Add them up for a final total.
Hi S,
It's five hundred and fifty five.
I'll try your multiply answer, thanks.

I've been wondering why it's 3x BYTEs and not 2xBYTEs, which is also possible and may work better really. I'll look into it, as it was a while ago when this was set-up and it maybe my preference, in order to read it in a Terminal.
Cheers, C.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,730
Is it hex 53 or decimal 53? Hex 053 is a capital "S", whereas a decimal 53 is the ASCII "5", which makes more sense.
Sending "555" in ASCII can be converted to a binary by converting each ASCII string to a numeric value, with a function such as StrValW or StrValL
Or, take each byte value and multiply it by the position in the byte array, so first "0x53" (if that is what it is) is converted to a binary "5" and then multiplied by 100. The next is converted to a number and multiplied by 10 and final is just converted. Add them up for a final total.
Hi S,
It took some experimenting, remembering 'OR' and brackets, but it now shows APPROX what it should do. I think the APPROX may be due to reading the 3xBYTES at slightly different time, which can be ironed out.

Anyway, after the the ORing and converting the number to between 1000 and 2000, I connected it to the first SERVO, and now when the BASE joystick is moved, the REMOTE-SERVO moves :)

There is a long time lag, as the joystick number goes through the air, then through my CODE in REMOTE MASTER, then via SPI to REMOTE SLAVE, then through todays calc and into the SERVO, so there's lots of things to look at, but at long last everything seems to be somewhat working.
Thanks, C.
 
Top