Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Add GPS/PARSE to 8xSERVO-MOTOR CODE in Oshonsoft

As usual, this thread has been "continued" over on another forum, with all the offending reasons for the code blocking issues being pointed out there that we were never privy to unless you try to piece together all the various bits and pieces about this project spread out across multiple forums/threads.

They get 1/2 the story, we get 1/2 the story. Once they "fix" their half on the other forum , it'll probably reappear here with a bunch of new code that screws up the half shown here.

It's no wonder this project has been going on for years now...
Hi T,
I'm sorry about this!
The reason is a valuable contributor who has helped me, since I first came on these forums, moved from ETO to AAC.
The two forums have some different contributers, with slightly different ideas.
Anyway, I try to keep both forums informed and involved.
I try not to mix up theads, with the same question. Sometimes I need to ask a question, which would break the flow of a thread, so I ask it on the opposite forum, so that it's separate.
It's not meant for confusion, and if you stay on one forum, I try to keep each thread flowing.
Sorry for this, but it just happened!
C
 
I wrote most of that (this) code but gave up when delays and software serial, which also blocks, was added. I wrote it in C on a 18F2620 and then converted to basic. Unfortunately, a disk crash cause it all to be lost. I think it ran at 32MHz using the internal oscillator. Actually just looked and found an early version that used PPS to steer the CCP1 output to the PORTB pins and it uses 32 MHz. Couldn't figure out pointers in basic so changed it.

Mike.
Hi M,
I have just speant an hour searching for the person who wrote an explanation of this CODE that I save as a note. It was you.
Anyway, thanks for converting the BASIC CODE from C, I've been working on it everyday since!
At the moment, the SERVO only section is running SIM and LIVE, and it's taking me quite a while to understand quite how it works.
I'm clarifying your CODE to suit my 'eye' while noting the INTERRUPT timing.

I have a mate that helps me (with limited time) and we both came to the same idea regarding INTERRUPTS, 'SHIFT REGISTER', 'UART' and MAIN LOOP.
This timing is new to me, and all BYTES, SHIFTS and LOOP need to be interwoven together.
At the moment this is beyond me, but logically, I can see it. Now to implement it.
Cheers, C.
 
It's no wonder this project has been going on for years now...
Hi T,
This has been going a long time, and I've had lots of skilled help from you all, in multiple forums, including maths, computing, electronics, and RC etc. over the years.
This project is far beyond my capabilities, and if you follow all of it you will see PCB production, SMD soldering, D/S galore, lots of peripherals etc, that all needed to be learned posted and answered by someone.
If you look at a similar project in the real world intead of this bunch, there's a facory of stations, desks, programmers and managers with meetings.
'Patience is a virgin'
C.
 
Last edited:
I wrote most of that (this) code but gave up when delays and software serial, which also blocks, was added. I wrote it in C on a 18F2620 and then converted to basic. Unfortunately, a disk crash cause it all to be lost. I think it ran at 32MHz using the internal oscillator. Actually just looked and found an early version that used PPS to steer the CCP1 output to the PORTB pins and it uses 32 MHz. Couldn't figure out pointers in basic so changed it.

Mike.
Hi M,
I've just spotted your CCP output comment. This PIC only has 2x PINs for this. I spent quite a time trying to get more channels, and the SHIFT REGISTER was introduced.

I think I've figured out how the SHIFT REGISTER works! If I'm correct, then it can work with 5X Channels if wished. So the gap between the 5th CHAN and the FRAME time, will be >10mS. Also there is a gap between each channel 1 and 2mS.

There are 3x PINs that control the shift register, all BIT values.

For now don't think about high to low, or low to high.

1/ 1=RUN, 0=RESET= All output PINS = 0

2/CLK

3/ 1=1 0=0

For this example the LEFT PIN is CH1

The TIMER is set to the time of CH1 ANGLE 'say' 1500us = 1/2 way

Set PIN 1/ to 1-RUN and set 2/ to 1=1 Set 3/ to 1xCLK a 1xBIT is shifted into CH 1.

Wait for the TIMER FLAG (while setting the TIMER to the time of CH2 ANGLE 'say' 1000us = 1/2 way) then

Set 1/ to 1-RUN and set 2/ to 0=0 Set 3/ to 1xCLK a 0 BIT is shifted into CH1 and the 1 BIT shifts to CH2.

Wait for the TIMER FLAG (while setting the TIMER to the time of CH3 ANGLE 'say' 2000us = CW) then

Set 1/ to 1-RUN and set 2/ to 0=0 Set 3/ to 1xCLK a 0 BIT is shifted into CH1 shifting the 0 BIT in CH1 to CH2 and the 1 BIT shifts to CH3.

and so on.

All of the CH times are totalled up, and subtracted from the FRAME time 20000us,then wait till the FRAME time has elapsed.

If 5xCHANNELS are used, then once the 1BIT in CH5 has finished it's TIME, then set PIN1 (reset) to 0 and reset all BITs to 0.

Let me know if I'm incorrect!
C.
 
Last edited:
You are correct but, if I remember correctly, the on time is always 500uS followed by an off time equal to the servo time less 500uS.

The gap time is how you explained it.

Mike.
 
You are correct but, if I remember correctly, the on time is always 500uS followed by an off time equal to the servo time less 500uS.

The gap time is how you explained it.

Mike.
Hi M,
My mate asked me how the SHIFT REGISTER work?, as he prefers the PIC 8xPIN PWM idea. On one of the forums, possibly this one, this was discussed and how the SHIFT REGISTER was introduced.
I haven't been able to reverse engineer your CODE, so I re-thought it!
I wrote him an explanation that I think is better than my previous one in #324, so I edited it.
Perhaps you could have a look and see if it is better, please?
C
 
On one of the forums, possibly this one, this was discussed and how the SHIFT REGISTER was introduced.
I posted the original pure interrupt & shift register servo routines, I believe.

This is a shift register version from one of my working projects; it's in CCS C for a PIC24 / DSPIC with pulse capable CCP.
(Just the output section of a rather larger servo library that includes timed ramps, zero offsets and travel limits etc.)


Initialisation:

C:
  // T3 = 16 bit timer used as the clock source for CCP, input 64 / 8 = 8MHz
  setup_timer3(TMR_INTERNAL | TMR_DIV_BY_8, 0x0007);
 
  // Output compare 1, used to control the shift register clock
  setup_compare(1, COMPARE_TIMER3 | COMPARE_CONT_PULSE);

Routine called by OC1 compare interrupt:

C:
void servo_interrupt(void) {
    
    if(s_index < NUM_SERVOS) { // All servos already done?
        // No, do next servo
        
        // Set the duration for this output, as a new offset
        // from the last compare time.
        s_time_set = s_time_set + s_time[s_index];
        
        // Write the compare time to CCP 1 register.
        // Each shift reg clock pulse will be high for 10uS.
        set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);

        // Increment index for next servo time value
        s_index++;
        
        // Write the shift data in to low
        output_bit(SERVO_DATA, 0);
    }
    else {
        // Add a fixed time increment for delays before
        // restarting the sequence.
        
        s_time_set = s_time_set + SERVO_INTERVAL; // add 1.5mS for the next interrupt
        // Update CCP
        set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);
        
        
        if(s_index > 9) {
            // 10 * average 1.5mS = 15mS, a reasonable frame repeat time
            
            // Set up for a new sequence
            s_index = 0;           

            
            //s_time_now = get_timer3(); // Get the sync timer present count and           
            s_time_set += 1000; // set a delay for the start of the first pulse

            // Write the compare time to CCP 1 register.
            set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);
            
            output_bit(SERVO_DATA, 1); // Write the shift data in to high
            
            // The next compare will start the first output pulse [channel 0]
            
            servo_frame_count++;
            
        }
        else {
            s_index++;
        }
        
    }
 
}
 
I posted the original pure interrupt & shift register servo routines, I believe.

This is a shift register version from one of my working projects; it's in CCS C for a PIC24 / DSPIC with pulse capable CCP.
(Just the output section of a rather larger servo library that includes timed ramps, zero offsets and travel limits etc.)


Initialisation:

C:
  // T3 = 16 bit timer used as the clock source for CCP, input 64 / 8 = 8MHz
  setup_timer3(TMR_INTERNAL | TMR_DIV_BY_8, 0x0007);
 
  // Output compare 1, used to control the shift register clock
  setup_compare(1, COMPARE_TIMER3 | COMPARE_CONT_PULSE);

Routine called by OC1 compare interrupt:

C:
void servo_interrupt(void) {
   
    if(s_index < NUM_SERVOS) { // All servos already done?
        // No, do next servo
       
        // Set the duration for this output, as a new offset
        // from the last compare time.
        s_time_set = s_time_set + s_time[s_index];
       
        // Write the compare time to CCP 1 register.
        // Each shift reg clock pulse will be high for 10uS.
        set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);

        // Increment index for next servo time value
        s_index++;
       
        // Write the shift data in to low
        output_bit(SERVO_DATA, 0);
    }
    else {
        // Add a fixed time increment for delays before
        // restarting the sequence.
       
        s_time_set = s_time_set + SERVO_INTERVAL; // add 1.5mS for the next interrupt
        // Update CCP
        set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);
       
       
        if(s_index > 9) {
            // 10 * average 1.5mS = 15mS, a reasonable frame repeat time
           
            // Set up for a new sequence
            s_index = 0;          

           
            //s_time_now = get_timer3(); // Get the sync timer present count and          
            s_time_set += 1000; // set a delay for the start of the first pulse

            // Write the compare time to CCP 1 register.
            set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);
           
            output_bit(SERVO_DATA, 1); // Write the shift data in to high
           
            // The next compare will start the first output pulse [channel 0]
           
            servo_frame_count++;
           
        }
        else {
            s_index++;
        }
       
    }
 
}
Hi R,
Yes, I had forgotten.
I think probably M, converted it to BASIC for me? , as I don't speak 'C' :(

Following my explanation in #324, I'm going to attemp to write the CODE in BASIC myself, as an experiment.
If it works, I'll post it and hopefully it will be the same and as good as yours?
Thanks,
C
 
I posted the original pure interrupt & shift register servo routines, I believe.

This is a shift register version from one of my working projects; it's in CCS C for a PIC24 / DSPIC with pulse capable CCP.
(Just the output section of a rather larger servo library that includes timed ramps, zero offsets and travel limits etc.)


Initialisation:

C:
  // T3 = 16 bit timer used as the clock source for CCP, input 64 / 8 = 8MHz
  setup_timer3(TMR_INTERNAL | TMR_DIV_BY_8, 0x0007);
 
  // Output compare 1, used to control the shift register clock
  setup_compare(1, COMPARE_TIMER3 | COMPARE_CONT_PULSE);

Routine called by OC1 compare interrupt:

C:
void servo_interrupt(void) {
   
    if(s_index < NUM_SERVOS) { // All servos already done?
        // No, do next servo
       
        // Set the duration for this output, as a new offset
        // from the last compare time.
        s_time_set = s_time_set + s_time[s_index];
       
        // Write the compare time to CCP 1 register.
        // Each shift reg clock pulse will be high for 10uS.
        set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);

        // Increment index for next servo time value
        s_index++;
       
        // Write the shift data in to low
        output_bit(SERVO_DATA, 0);
    }
    else {
        // Add a fixed time increment for delays before
        // restarting the sequence.
       
        s_time_set = s_time_set + SERVO_INTERVAL; // add 1.5mS for the next interrupt
        // Update CCP
        set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);
       
       
        if(s_index > 9) {
            // 10 * average 1.5mS = 15mS, a reasonable frame repeat time
           
            // Set up for a new sequence
            s_index = 0;          

           
            //s_time_now = get_timer3(); // Get the sync timer present count and          
            s_time_set += 1000; // set a delay for the start of the first pulse

            // Write the compare time to CCP 1 register.
            set_compare_time(1, s_time_set, s_time_set + SERVO_CLOCK);
           
            output_bit(SERVO_DATA, 1); // Write the shift data in to high
           
            // The next compare will start the first output pulse [channel 0]
           
            servo_frame_count++;
           
        }
        else {
            s_index++;
        }
       
    }
 
}
I remember this as my first code used peripheral steering to map the output of the CCP module to the pins of PORTB. You didn't understand how the gaps worked in my code (so each output would start on a 2.5mS period). Hence the shift register was added. Never could figure out how to do PPS via pointers in Oshonsoft.

Mike.
 
I remember this as my first code used peripheral steering to map the output of the CCP module to the pins of PORTB. You didn't understand how the gaps worked in my code (so each output would start on a 2.5mS period). Hence the shift register was added. Never could figure out how to do PPS via pointers in Oshonsoft.

Mike.
Hi M,
This is quite complicated, and figuring out how all of it works, including D/S head scratching is difficult.
Regarding POINTERS, even though Oshonsoft has POINTERs in it's language, I think it was pointed out to me that they are not full POINTERs, so they weren't adopted. This also is difficult to follow!

EDIT: I notice that POINTERS and BYREF have been updated. I'm unskilled enough to try it, but some of you may find it works
C.
 
Last edited:

Latest threads

New Articles From Microcontroller Tips

Back
Top