PIC Controlled clock movement hack?

Discussion in 'Programmer's Corner' started by Tigthwad, Feb 25, 2013.

  1. Tigthwad

    Thread Starter Member

    Oct 27, 2009
    31
    1
    My son has been having a blast creating circuits, soldering them, and doing some light programming (12 year old, just learning to control things in C without a real deep understanding of what is happening still). He built a circuit to control a 360 degree servo mechanically attached to the adjustment wheel of a clock mechanism. The goal was to make the hands move fairly fast (slightly over 2 hours per real minute) and at one point rotate it at 1 hour per 2 seconds.

    He managed to get the hour per 2 seconds point working using the hacked servo (modified to be 360 rotation). The issue he is having is with the slower movement. He has tried a lot of different PWM values but he can't get a smooth/slow rotation....or even consistent. I am afraid what he is trying to do isn't actually even possible?

    It looks like inertia may be working against him...at 1500 uS pulse (with 15mS between pulses) the servo is held at center. at ~1460 uS it will move usually, but it's a big jump...2-3 minutes tick off at a time. He can't get a smooth movement until about 1420 uS or so of on time and then it is moving faster than they want.

    Any ideas?
     
  2. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    A continuous rotation RC servo is the wrong tool for the job, it will be erratic and have very poor speed control at very low RPMs.

    Since you already have a PIC micro the ideal motor is a stepper motor which can do a flawless perfect speed, ideal for clocks. :)

    Check out ebay for some really cheap little $5 stepper motors and drivers. Alternatively, you can get free steppers from inside any old bubblejet printer, and drive them with a few transistors or a common ULN2003 or ULN2083 IC.

    Here is a stepper motor clock I made for fun, it has one "hand" and takes exactly 6 hours for ONE rotation, it is very accurate!

    [​IMG]
     
    Tigthwad likes this.
  3. tracecom

    AAC Fanatic!

    Apr 16, 2010
    3,869
    1,393
    According to the clock in the picture, is it 12:35 am, 6:35 pm, 12:35 pm, 6:35 am, or none of the above?
     
  4. Tigthwad

    Thread Starter Member

    Oct 27, 2009
    31
    1
    Awesome, I have ordered 3 stepper motors with driver boards (never hurts to have spares...).

    Any pointers on some sample C Code for microchips to drive them? I would like to find him a start point to work with. My only experience with steppers was in a mini cnc build and I don't interface with them really...it was a kit and then controlled by the PC
     
  5. John P

    AAC Fanatic!

    Oct 14, 2008
    1,632
    224
    Here is a video which shows a project I set up as a result of a discussion here. The question was how a clock could be made with a second hand which would take 60 steps to complete a revolution, if the motor driving it had 48 steps per revolution.

    If you have a student of the dark art of electronics there, you might ask him why the motor makes a whining sound 4 steps out of 5 and is silent on the 5th. Maybe the LEDs on the breadboard offer a clue to what's happening?

    http://www.youtube.com/watch?v=EGwNYo69y2o
     
  6. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    YES. :D

    It's a 6 hour clock face as you guessed, with either 12:00 at the top or 6:00 at the top.

    In use you always know which of the 6hour cycles you are in, ie if near lunchtime you know it says 12:35, or if the sun's coming up you know its 6:35 in the morning. Some of the earliest mechanical clocks had a single moving hand.

    There are some C code examples for timing on this page;
    http://www.romanblack.com/one_sec.htm
    That can give exact seconds from any xtal value, and done fairly easily in any timed event like a timer interrupt or by testing a timer bit.

    The beauty of the functions is that neither the xtal freq or the freq of the timed event matters, you just change two numbers and they will still make perfect average seconds for clock type use.
     
  7. Tigthwad

    Thread Starter Member

    Oct 27, 2009
    31
    1
    Is there any reason this:

    Code ( (Unknown Language)):
    1. C code for a 1 second period with a 1MHz timer (4MHz xtal);
    2.  
    3.     // uses 1 variable; unsigned long bres
    4.     // gets here every TMR0 int (every 256 ticks)
    5.  
    6.     bres += 256;    // add 256 ticks to bresenham total
    7.  
    8.     if(bres >= 1000000) // if reached 1 second!
    9.     {
    10.         bres -= 1000000;    // subtract 1 second, retain error
    11.         do_1sec_event();    // update clock, etc
    12.     }
    Can't be split into smaller increments to do perfect 1/2 or 1/4 second timing? Something like:
    Code ( (Unknown Language)):
    1. C code for a half second period with a 1MHz timer (4MHz xtal);
    2.  
    3.     // uses 1 variable; unsigned long bres
    4.     // gets here every TMR0 int (every 256 ticks)
    5.  
    6.     bres += 256;    // add 256 ticks to bresenham total
    7.  
    8.     if(bres >= 500000)  // if reached .5 second!
    9.     {
    10.         bres -= 5000000;    // subtract .5 second, retain error
    11.         do_halfsec_event(); // update clock, etc
    12.     }
     
  8. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Can you get the frequency higher so that it only annoys dogs?
     
  9. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    No, that will work fine.
     
  10. John P

    AAC Fanatic!

    Oct 14, 2008
    1,632
    224
    Ha ha. As far as I remember, I found that if you want hardware-based PWM output on a selectable pin of that processor (PIC16F690) you're limited in which pins can be used in combination. I couldn't get it to do what I needed in driving the outputs for 4 motor coils, and of course it was just a throwaway project designed to prove that it could be done. Maybe with extra hardware I could have used the built-in PWM, but the easy way to make it work was to do the PWM in software. That imposes a conflict over how much resolution you want the duty cycle to have, versus the frequency. I think I ended up with 400Hz, and that's what's audible. There would also be the issue of what frequency the ULN2003 driver would be capable of working at, before switching losses become a problem. It was definitely a "quick and dirty" design!
     
  11. Tigthwad

    Thread Starter Member

    Oct 27, 2009
    31
    1
    Here is what we have determined we need so far:

    Motor being used has specs of:
    Step angle: 5.625 x 1/64
    Reduction ratio: 1/64

    Total steps = 32,768 (8 rotations at 64 steps with a 1/64 reduction)
    Total time = 480 seconds

    For 10 seconds the step rate needs to be much faster...20,480 steps of the total taken in this time. The remainder of the steps will be split to a before/after scenario (a button press will start the 10 second speed portion).

    Would we be better off counting steps or running an 8 minute timer that steps at the speed needed? We have some events (buzzer sounding) that happen at specific time intervals etc.

    We are still trying to understand how to implement TMR0 (or 1 or 2) for the 16F628A chip and how to use interrupts...it's a dark art I think!
     
  12. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    You don't really have to use interrupts in such a simple application.

    Just manually wait in your code for the the TMR0 int flag to be set, then clear the flag. If TMR0 is set to 1MHz that int flag will get set every 256 uS.

    Like this;
    Code ( (Unknown Language)):
    1.  
    2. while(1)       // main operating loop
    3. {
    4.   while(INTCON.TMR0IF == 0) continue;   // wait for int flag
    5.   INTCON.TMR0IF = 0;                // clear int flag
    6.   // code gets here every 256 uS!
    7. }
    8.  
    Maybe if you post your full code we can help with it?
     
  13. John P

    AAC Fanatic!

    Oct 14, 2008
    1,632
    224
    I'm very dubious that the fast step rate you mentioned, over 2000/sec, is possible with that kind of motor. Must you really have that speed?
     
  14. Tigthwad

    Thread Starter Member

    Oct 27, 2009
    31
    1
    I have the same concern. The requirements may be changed based on the hardware ability...it's part of a performance by my 12 year old sons group so the requirements can be adjusted as needed.
     
  15. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    Your original post specced "1 hour per 2 seconds" as maximum speed, so that is 1/12th of a rotation over two seconds, or 24 seconds per full rotation.

    That gearmotor has 64:1 gearing so to get 24 seconds per final rotation requires 24/64 or 0.375 seconds per motor rotation.

    I think that is do-able easy enough on that motor as it is only 2.67 motor rotations per second. It may not self start well at 2.67 RPS, you might need to accelerate it over a few steps.
     
  16. Tigthwad

    Thread Starter Member

    Oct 27, 2009
    31
    1
    The clock is being run using the adjustment wheel on the back. 1 revolution of the adjustment wheel = 1 hour on the clock. That means 1/2 rotation per second. This feels quite fast and maybe isn't possible with the gearing involved in the motor (the motor would be rotating at 32 times a second).

    What is the proper way to code an acceleration? I know my CNC software uses a trapezoidal ramp at start/stop but I don't see the code behind that of course.
     
  17. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    OK, there's no way that motor will do 32 revs/sec, not without pushing it's spec and going to a lot of trouble.

    Just use a normal (ungeared) stepper motor, and you only need 0.5 RPS.

    You won't need to accelerate the stepper motor now, since it only needs to start at 0.5 RPS which should be fine.
     
  18. Tigthwad

    Thread Starter Member

    Oct 27, 2009
    31
    1
    Hi all...I got my stepper motor (28BYJ-48) and driver board (UN2003 board from geeetech.com). I tried to get a simple rotation code running but it isn't working. I am using a 12F609 with pins 5,4,2,1 connected to pins 1,2,3,4 on the driver board. I am supplying 5v and ground on the board using the first 2 pins. The code as written lights an LED but the motor does nothing.

    Any ideas?

    Code ( (Unknown Language)):
    1.  
    2. /*
    3.  * File:   StepMain.c
    4.  * Author: Dad
    5.  *
    6.  * Created on March 8, 2013, 10:31 PM
    7.  */
    8. #define _XTAL_FREQ 1000000
    9. #include <stdio.h>
    10. #include <stdlib.h>
    11. #include <xc.h>
    12.  
    13. __CONFIG(MCLRE_ON & CP_OFF & WDTE_OFF & FOSC_INTOSCIO);
    14.  
    15. #define I_O_OUT     0       // standard TRIS definitions
    16. #define I_O_IN      1
    17. #define P_ON        1       //
    18. #define P_OFF       0
    19. #define P1          GP5
    20. #define P2          GP4
    21. #define P3          GP2
    22. #define P4          GP1
    23. #define P1_TRIS     TRISIO5
    24. #define P2_TRIS     TRISIO4
    25. #define P3_TRIS     TRISIO2
    26. #define P4_TRIS     TRISIO1
    27.  
    28. void forward()
    29. {
    30. P1 = P_ON;
    31. __delay_ms(2);
    32. P1 = P_OFF;
    33.  
    34. P1 = P_ON;
    35. P2 = P_ON;
    36. __delay_ms(2);
    37. P1 = P_OFF;
    38. P2 = P_OFF;
    39.  
    40. P2 = P_ON;
    41. __delay_ms(2);
    42. P2 = P_OFF;
    43.  
    44. P2 = P_ON;
    45. P3 = P_ON;
    46. __delay_ms(2);
    47. P2 = P_OFF;
    48. P3 = P_OFF;
    49.  
    50. P3 = P_ON;
    51. __delay_ms(2);
    52. P3 = P_OFF;
    53.  
    54. P3 = P_ON;
    55. P4 = P_ON;
    56. __delay_ms(2);
    57. P3 = P_OFF;
    58. P4 = P_OFF;
    59.  
    60. P4 = P_ON;
    61. __delay_ms(2);
    62. P4 = P_OFF;
    63. }
    64. /* Main program */
    65. void main()
    66. {
    67. P1_TRIS = I_O_OUT;
    68. P1 = P_OFF;
    69. P2_TRIS = I_O_OUT;
    70. P2 = P_OFF;
    71. P3_TRIS = I_O_OUT;
    72. P3 = P_OFF;
    73. P4_TRIS = I_O_OUT;
    74. P4 = P_OFF;
    75.  
    76.  
    77. while (1)
    78. {
    79.     forward();
    80. } // end while
    81. } //end main
     
  19. Tigthwad

    Thread Starter Member

    Oct 27, 2009
    31
    1
    I figured it out. There needed to be a jumper between 5v and vss on the stepper board. Not sure why you wouldn't have one there but I only discovered it by looking on youtube for examples of others using it.

    Motor turns now, working to see what max speed I can do. Writing some code to try to ramp up the speed...not sure if that will help with overall speed.
     
  20. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    Looks like your code is using half stepping.

    You can improve the code a lot (and simplify it!) by writing to the whole port at one time, instead of turning each pin on or off;

    GPIO = 0b00000011;
    delay_mS(2);

    GPIO = 0b00000110;
    delay_mS(2);

    GPIO = 0b00001100;
    delay_mS(2);

    GPIO = 0b00001001;
    delay_mS(2);

    Those 4 steps gives you standard full-step "2 phase on" drive. Obviously you can add extra steps to make it into half-stepping.
     
Loading...