PIC16F84A using pulsout and TMR0


Closed Thread
Results 1 to 33 of 33
  1. #1
    Join Date
    Nov 2006
    Posts
    33

    Post PIC16F84A using pulsout and TMR0

    Hi All

    I had so touble on the Pulsout and tmr0 interrupt.
    Can I send a pulse in 4.32 second to the stepper motor driver (UCN5804B)and at the same time doing tmr0 interrupt to do the time and date.
    For example: 8am start run the stepper motor in period=4.32second and 5pm the stepper motor back to its initial position.

    Below are my code: Please give advice thanks you very very much
    The code is ok i think ,but the period is NOT what I want.

    ' The program is doing the solar tracker using stepper motor 1.8degree(5V,1A)
    ' ANd it must be track in 15 degree per hour
    ' The clock using TMR0 is to activate the tracker to start and stop.
    ' I will also need to display the time on the LCD
    '
    ' For Example: When 8 am the stepper motor start run in 15 degree per hour.
    ' gearbox 100:1 RATIO
    '
    ' This code that I write just run in period 65.53 milisecond.
    ' The code is NOT what i need.

    'WHAT I NEED IS TO SEND PULSE IN 4.32 second.
    'BELOW PULSOUT 0,6553 WHICH IS ONLY 65.53MILISECOND.
    ' Code below can run but the pulsout time period is not what I want (period=4.32 second)

    hour VAR BYTE
    bm VAR BYTE
    bs VAR BYTE
    day VAR WORD
    month VAR BYTE
    year VAR WORD
    s VAR BYTE
    t VAR BYTE

    hour=0:minute=0:second=0:

    'TMR0 will interrupt every 65,536 milliseconds

    OPTION_REG=%01010111 ' prescaler= 1:256
    INTCON=%10100000

    ON INTERRUPT GoTo start
    TRISB=0 ' all port b set to output
    High 1 ' stepper motor stop (Enable=high)
    High 2 ' CW direction

    '************************************************* ************************************
    main:
    PulsOut 0, 6553 ' clock pulse to the stepper motor driver UCN5804B
    ' 65.53 milisecond
    GoTo main
    ************************************************** ************************************

    ' Interrupt service routine (ISR)

    Disable ' Disable interrupts during interrupt handler
    start : t = t + 1 ' Count pieces of seconds
    IF t < 15 Then exit ' 15 ticks per second (65.536ms pertick)

    '**********Time elasped = 1 second ***********
    t = 0
    bs = bs + 1
    IF bs >= 60 Then
    bs = 0
    bm= bm + 1
    IF bm >= 60 Then
    bm = 0
    hour = hour + 1
    IF hour >= 24 Then
    hour = 0

    EndIF
    EndIF
    EndIF

    exit: INTCON.2 = 0 ' Reset timer interrupt flag
    Resume
    End

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    I guess what you want is one pulse every 4.32s, in other words a frequency of 0.2315Hz.

    Code:
    'Produce squarewave on PortB.0 period~4.32s, 50% dutycycle.
    
    Loop var Word
    
    Main:
     High PortB.0
     For Loop = 0 to 2160       'Loop here for ~2.16s, tweak to match.   
       PauseUs 1000
     Next
     Low PortB.0
     For Loop = 0 to 2160       'Loop here for ~2.16s, tweak to match. 
       PauseUs 1000
     Next
    Goto Main
    Since the Pause statement in the For-Next loop is shorter (1mS) than what your interrupt period is (65mS) the ISR will still run.

    However, your time-keeping will not be very accurate. You're only getting 983mS each second, give or take, 65536uS * 15 = 983040uS.

    /Henrik Olsson.

  3. #3
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    too bad PIC16F84a don't have 2 timers... The Henrik solution will work indeed, but i'll suggest to use shorter PAUSEUS, let's say 10uSec... OR a loop of @ nop.

    If you need accuracy, you may decide to fine-tune it using MPLAB stopwatch OR measure it using an extra i/o and a scope.

    Another solution... Use 2 variables, flags and 1 Timer.

    There's many different ways.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  4. #4
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post Thanks for the reply....some question below....

    Hi all

    Thanks to HenrikOlsson and mister_e that give me the marvelous advice.
    I had tested it on the lab but the period is 4.6 and something 4.5. After I change it to For 0 To 2020 it will work 4.3 and something 4.2.
    I just measure it using stopwatch.
    For accuracy of the clock I will assign TMR0 = 12 {((fosc/4)*(256-12)*256)=0.9994}. Is that OK????

    Mister_e has suggest me to use 10us pause. Which mean that the for loop have to increase to 216000 rite???
    Sorry..I don't undestand the statement below:-

    *****If you need accuracy, you may decide to fine-tune it using MPLAB stopwatch OR measure it using an extra i/o and a scope.
    Another solution... Use 2 variables, flags and 1 Timer.*****************

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    I don't follow you on the math....
    If you reload TMR0 with 12 each interrupt you'll get (256-12) * 256 = 62464uS between each interrupt.

    What kind of accuracy do you need? With the prescaler set to 1:256 and a TMR0 reload value of 178 you'll get (256-178)*256 = 19968uS between each interrupt plus a little for the time it takes to reload.

    Another way would be to use an external xtal for TMR0, with a standard 32.768 watch xtal and the prescaler set to 1:128, you'll get one interrupt each second.

    MPLAB have a simulator where you can run the code, it has a stopwatch function that can be used to "measure" how long a certain piece of code takes. I've never used it myself.

    /Henrik Olsson.

  6. #6
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    Instead of using StopWatch, you may measure it in real-world. Use a scope and measure the time using an extra I/O.

    Example:

    High AextraIO
    ' code you need to evaluate
    LOW AextraIO

    You place your scope (or frequency meter, etc etc) on the AextraIO pin and you measure it.

    something handy for your Timer Calc
    http://mister-e.org/pages/utilitiespag.html
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  7. #7
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post store 365 data..

    Thanks to the advice and reply, I really appreciated it.

    From the interupt I know that I could add in the date.Such as day=day+1,month=month+1 and so on....

    I have another matter which is WHERE can i store 365 sunrsie time?
    My algoritm is just like that:-
    1 jan 2006 the sunrise time is 6:10 motor start run and 2 jan 2006 the sunrise time is 6:15 and so on.

    I know that it is impossible for me to store 365 data in the PIC16F84A eeprom.
    Can I store my data into the program memory or RAM?????

    Please advice and thanks you very much...

  8. #8
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    you could save it to the codespace and play around the following
    http://www.pbpgroup.com/modules/wfse...p?articleid=10

    or, use an external EEPROM.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  9. #9
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post LCD question

    Hi all
    Thanks for the reply.

    Just now on the lab I have try to display the word in the LCD but NOT SUCCESS.
    Below is the code I follow all the connection on the PBP manual using PIC16F84A. LCD is bought from the www.cct.com.my.


    ‘ Set LCD Data port
    DEFINE LCD_DREG PORTA
    ‘ Set starting Data bit (0 or 4) if 4-bit bus
    DEFINE LCD_DBIT 0
    ‘ Set LCD Register Select port
    DEFINE LCD_RSREG PORTA
    ‘ Set LCD Register Select bit
    DEFINE LCD_RSBIT 4
    ‘ Set LCD Enable port
    DEFINE LCD_EREG PORTB
    ‘ Set LCD Enable bit
    DEFINE LCD_EBIT 3
    ‘ Set LCD bus size (4 or 8 bits)
    DEFINE LCD_BITS 4
    ‘ Set number of lines on LCD
    DEFINE LCD_LINES 2
    ‘ Set command delay time in us
    DEFINE LCD_COMMANDUS 2000
    ‘ Set data delay time in us

    Pause 100 ' Wait for LCD to startup
    LCDOut $fe, 1 ' Clear LCD screen
    LCDOut "Hello" ' Display Hello

    End

    Please advice and thanks

  10. #10
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Double check all connections. Do you have the pullup resistor on RA4?

    /Henrik Olsson.

  11. #11
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    AND never finsih your program with a single END... use a endless loop or PBP STOP.
    Code:
        LCDOUT $FE,1,"Your stuff"
    Loop:
        Goto Loop
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  12. #12
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post using 2 interupt

    Hi all,
    Thanks for the reply.

    Regarding the LCD everyting look fine in my circuit. After power on the, the LCD come 16 small black square on the screen but it does not display "Hello".

    Regarding the website that u given to me i'm not very understand. Do you have the simple one and is in the pure PicBasic Pro language. Besides in the website I noticed one things which we can add 2 or more interrupt at the same time..But I go thru this I not really understand.....Thanks

    Below is the statement that provide by the mister_e:-

    ****************too bad PIC16F84a don't have 2 timers... *********
    ************************************************** ******
    I'm planned to use the PIC16F876A there got timer 0 ,1 and 2.

    (1) Is that possible using 2 interrupt in a single program.??

    (i) One interrupt (tmr0) is for the clock pulse to send to the stepper motor driver
    (ii) One interrpt(tmr1) is for the 1 second elapsed.

    If the above possible...Does it mean that in the program I need to have two
    ON INTERRUPT code..

    Please guide me thru this..... Thanks you all very very much........
    Last edited by DragonBall_6; - 5th December 2006 at 09:43.

  13. #13
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Basicly you can have as many interrupts sources as the PIC has (TMR0, TMR1, USART, RB0, RBChange, CMP, ADC, whatever.....). When the program interrupts and starts executing the ISR (InterruptServiceRoutine) you need to check what caused the interrupt and act uppon it accordingly.

    My approach to this would be to use an external 32.768kHz xtal, set the TMR of your choise up to generate an interrupt at 100Hz, then in the ISR count those ticks. When you have 100 ticks you have a second. When you have 216 ticks, toggle your step pin.

    Code:
    Ticks var byte             '1/100th seconds
    StepTicks Var Byte      '1/100th seconds, used for step pulse timing
    Seconds var Byte        'Seconds
    Minutes Var Byte         'Minutes
    Hours var Byte            'Hours
    Days var Byte             'Days, perhaps change this to a Word.
    
    Goto Main                  'Jump over ISR.
    
    DISABLE
    
    ISR:
    'Reload timer with correct value here, and restart it.
    
    Ticks = Ticks + 1
    If Ticks = 100 then
      Ticks = 0
      Seconds = Seconds + 1
        If Seconds = 60 then
          Seconds = 0  
            Minutes = Minutes + 1
            If Minutes = 60 then
              Minutes = 0
              Hours = Hours + 1
                If Hours = 24 Then
                  Hours = 0
                  Days = Days + 1
                Endif
            Endif
         Endif
    Endif
    
    StepTicks = StepTicks + 1
    If StepTicks = 216 then        '2.16s, time to toggle the step pin.
      StepTicks = 0
      Toggle StepPin
    Endif
    
    RESUME
    ENABLE
    
    Main:
    
    '---------------------------------------------
    'Your main code here.......
    'remember, NO time consuming commands, like Pause, sleep, nap etc.
    '----------------------------------------------
    Goto Main
    This is completely untested and just something to show you one approach. Also, I suggest you'll have a look at Darrel Taylors Instant Interrupts, search the forum, it makes interrupts a breeze but MAY be overkill in this application.

    About that LCD, if your connections ARE fine and matches your DEFINES then the only thing I can think of is a longer pause at the beginning OR you could try to increase the command and data delay with:
    Code:
    DEFINE LCD_COMMANDUS 2000    '<-----Increase this...
    DEFINE LCD_DATAUS 50             '<----and this.
    /Henrik Olsson.
    Last edited by HenrikOlsson; - 5th December 2006 at 06:42. Reason: Moved ISR to beginning.

  14. #14
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post Some LCD stuff

    Hi all

    One question to ask...

    I actually want to display "Time: 00:00:00"
    The LCD is working but the problem is it is only happen when i use crystal 2.4576Mhz.

    When i change my crystal to 4Mhz it will just display "00:00:00"
    without seeing the word "Time"..
    I had add the pull up esistor to 1k ohm and DEFINE LCD_COMMANDUS 1000. Is that ok???

    Why??
    Does it need to pause more longer???


    Thanks
    Last edited by DragonBall_6; - 7th December 2006 at 13:38.

  15. #15
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Do you have DEFINE LCD_COMMANDUS 1000 in your code? If that's the case try increasing that to 2000 to start with. If that doesn't help put a PAUSE 500 right at the beginning of the program, that will let the LCD startup for sure.

    If that doesn't help either, increase the COMMANDUS and DATAUS defines. Test with 10000 for COMMANDUS and 500 for DATAUS just to see if it helps. If it works, try to find the sweetspot just over where it stops working.

    /Henrik Olsson.

  16. #16
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson
    Hi,
    Do you have DEFINE LCD_COMMANDUS 1000 in your code? If that's the case try increasing that to 2000 to start with. If that doesn't help put a PAUSE 500 right at the beginning of the program, that will let the LCD startup for sure.

    If that doesn't help either, increase the COMMANDUS and DATAUS defines. Test with 10000 for COMMANDUS and 500 for DATAUS just to see if it helps. If it works, try to find the sweetspot just over where it stops working.

    /Henrik Olsson.

    Unless PBP has been fixed, I seem to remember that the DATAUS define was actually a byte define. In other words, if you specify DATAUS 257, it'll actually come out to be DATAUS 1. I could be wrong. The COMMANDUS is still a word define. I'll check a .lst file when I get home tonight to confirm that.
    JDG

  17. #17
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi Skimask,
    Thank you! I didn't know about that. Please let us know what you find out!

    /Henrik Olsson.

  18. #18
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson
    Hi Skimask,
    Thank you! I didn't know about that. Please let us know what you find out!

    /Henrik Olsson.


    I just checked it out.
    If you look in any .lst file that contains any LCD defines or usage, you'll see that the LCD_COMMANDUS is a word variable internal to PBP and, as I suspected, LCD_DATAUS is a byte variable internal to PBP. So, you can't use anything higher than 255 in LCD_DATAUS.
    Another thing to be changed in upcoming PBP manuals...
    JDG

  19. #19
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    well, i've NEVER use a higher value than 100uSec (50uSev typical) on those various LCD i work and i worked. I don't believe there's some on the market that will really need more than 100 uSec.

    If the LCD show only Black square it's because it fail to initialise properly or the contrast is set to max.

    Reasons to fail:
    • Too short startup delay, some may need up to secondes... try PAUSE 2000, if it works, reduce it 'till you find a comfort zone
    • Some wires are swapped between them
    • In 4 bit mode, you must use DB4, db5, db6,db7.... AND some model need to send unused pins somewhere gnd or VDD, check the datasheet
    • the R/W is not connected to GND
    • you're using RA.4 without pull-up resistors
    • your supply line is poor and noisy
    • you're using a xtal>4 MHZ and you didn't set HS config fuse
    Last edited by mister_e; - 9th December 2006 at 10:44.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  20. #20
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Thanks for verifying that Skimask!

    Steve, you are most certanly right about the timing, no LCD should need more than 100uS for data. But my advice of trying with 500 was not a very good one since I didn't know of the 8-bit clamp.

    All valid points from you Steve, Dragonballs problem seems to be timing related since it works when he's using a slower clock than 4Mhz. But at 4Mhz it seems to skip the first characters, if I understood it correctly.

    /Henrik Olsson.

  21. #21
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson
    Hi,
    Thanks for verifying that Skimask!

    Steve, you are most certanly right about the timing, no LCD should need more than 100uS for data. But my advice of trying with 500 was not a very good one since I didn't know of the 8-bit clamp.

    All valid points from you Steve, Dragonballs problem seems to be timing related since it works when he's using a slower clock than 4Mhz. But at 4Mhz it seems to skip the first characters, if I understood it correctly.

    /Henrik Olsson.


    I think the 500 idea was good enough since 500-256=244. Should be more than enough for a data delay...
    Put a 5 second pause at the beginning of the program, that'll extinguish any doubt about the power up on the LCD. If that don't fix it, it's something else.
    JDG

  22. #22
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default not seeing some code . . .

    Hi DragonBall_6,
    As I didn't see it listed in your code, do you have appropriate define osc X in your code and question 2 is have you set config fuses to HS when trying to use fast oscillator speed?
    JS

  23. #23
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post Advancing the project:

    Thanks to all the reply,

    After I change it to PIC16F876 and 4Mhz cystal, pause 500, commandus 2000 and dataus 1000. It is work.
    I had adding 4 button to increment the hrs,minute,day and month.
    I feel happy.THANK YOU ALL THAT PROVIDE ME A LOT OF INFORMATION.

    I have thinking to advancing my project by using the A/D function.
    The idea is get the input from the solar PV and sent into the PIC16F876.
    When the voltage is lower than 2 volt then motor stop and vice versa.
    The input voltage from the solar PV is up to 15 volt.

    Can someone help and guide me thru the basic part such as the initialization of the of the PIC???
    Possible that the PIC get the analog input above 5Volt????

    Any suggestion and Please advice....Thanks

  24. #24
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    If you look at the ADCIN command in the PBP manual you'll see how it's done in its simplest form. Basicly you set the pin you want to use to be an input via the corresponding TRIS register then you set the pin to analog via the ADCON1 register. Look up the ADCON1 register in the datasheet.

    Use a simple voltage divider between the solar PV (?) and the PIC pin. Take two resistors, one 2.2k and one 1k. Connect them in series across the 0-15V voltage with the 1k closest to ground. Connect the PIC pin to the junction between the two resistors. Don't forget that the ground from the solar PV must connected to the PICs ground. This will produce a voltage of 0 to 4.68V on the PIC pin for 0-15V from the solar PV. It will draw ~4.7mA from the solar PV.

    So....
    Code:
    DEFINE ADC_BITS 10             'Set ADC to produce 10bits
    DEFINE ADC_CLOCK 3            'Set ADC clock to internal RC
    DEFINE ADC_SAMPLEUS 50     'Set conversion time to 50uS
    
    TRISA.0 = 1                         'Set RA0 (pin2) to input.
    ADCON1 = %10001110           'Set RA0 to analog, internal Vref, result right justified. (See datasheet)
    
    SolarVoltage var WORD          'Store AD conversion result here.
    
    Loop:
    ADCIN 0, SolarVoltage                  'Read AN0, store result in SolarVoltage.
    LCDOUT $FE, 1, #SolarVoltage       'Display value on LCD
    Pause 500
    Goto Loop
    If you use the resistor values above the reading should vary somwhere around 0 - 958 give or take. (For a 0-15V input)

    /Henrik Olsson.

  25. #25
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post

    Thanks to the reply.
    Solar PV also called photovoltaic cell (direct absord sunlight and generate electricity).

    ***LCDOUT $fe,$1, #solarvoltage*****

    Thus, the LCD only can display the value not above 5 volt,am I right??
    If this is the case, if I want to display value above 5v on the LCD then is that possible.

    If I'm using 4 Mhz crystal, do I need to have this sentences ***DEFINE ADC_CLOCK 3****?????


    Thanks and please advice.
    Last edited by DragonBall_6; - 13th December 2006 at 00:40.

  26. #26
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default Maybe I am right . . .

    Quote Originally Posted by DragonBall_6
    Thanks to the reply.


    Thus, the LCD only can display the value not above 5 volt,am I right??
    If this is the case, if I want to display value above 5v on the LCD then is that possible.

    .
    Hi DragonBall_6,
    What the voltage divider does is input voltage based upon the resistors ratio into the pic pin and hopefully limit it's input voltage to TTL levels. You have to write the code to do the math and then output the voltage numbers to suit your purpose. If you store the ADC value in a byte variable then ( and I am going out on a limb here as I am as new to pic programming as you are ) you should be able to express that as a number from 0 to 255. So if 5 v = 255 (input pin at 5 v when solar panel is at 15 volts) then 255 = 15 volts.So with a given voltage divider you can express 15 volts incremented in 255 steps. Anyone out there who is more knowledgable please ring in!
    JS

  27. #27
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Just as Joe says, the two resistors forms a voltage divider that "divides" the voltage fed to it by the ratio between the two resistors. The upper one is 2.2 times larger than the lower one so will loose 2.2 times as many volts over that one than over the lower one. Or if you wish to put ohms law to the test:

    The total resistance is 3.2k, with a voltage of 15V there will be a current of (I = U / R) 4.6875mA flowing thru the two resistors. Now that current will produce a voltage over the lower resistor of (U = I*R) 4.6875V.

    Since the PIC's AD pin is connected in parallel with the lower resistor the PIC will "see" a voltage between 0 and 4.6875V when the voltage from the solar PV is between 0 and 15V.

    Now, in the code I showed you we set the ADCON1 register in a way that the ADC uses the PIC's powersupply as a reference voltage. What that means is that whatever the powersupply voltage is at the moment will produce the max reading from the ADC, so for the above to work it's important that the powersupply is stable at 5.0V.

    We also said
    Code:
    DEFINE ADC_BITS 10
    What that does is set the ADC code to give you a resolution of 10bits, or put another way, the result from the ADC will be between 0 - 1023. That is 0V on the input will give you 0 in SolarVoltage and 5V in will give you 1023 in SolarVoltage. The display will show that value, not the voltage.

    To get the display to show actuall volts you need to scale the value. With a powersupply of 5.0V each bit in the ADC result is 0.00488V (5/1024) so if the display shows 958 the voltage at the PIC pin is ~4.67V which in turn corresponds to ~15V from the solar PV. (See the voltage divider)

    Are you going to display the "real" voltage or just using the value to decide when to start the motor? If the later then you don't need to scale it at all, just use it as it is.

    The DEFINE ADC_CLOCK 3 tells the ADC module inside the PIC what clock source to use. It has nothing to do with the Xtal you are using to drive the PIC.

    /Henrik Olsson.

  28. #28
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default Just a simple add-on

    and '3' comes from the datasheet in the ADCON1 register setting (register 11-2, page 128) ADCS2 table
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  29. #29
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post A/D input

    Thanks to all the reply.
    I really appreciated it. I will try it at lab.
    Actually, I would like to receive A/D input from solar PV and after that there are 2 things to be done.
    First, IF the A/D input is less that 2 volt then stop the motor ELSE the motor activated.
    Secondly, at the same time A/D input from the solar pv is sent to the computer for processing and collected the data for every 15 minute. The result will be calculated and show in graph.
    It would need some knowledge of the visual basic as database and link between vb and ms excel.

    Somebody can guide me thru this?? Thank and please give advice.

  30. #30
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Just compare the value you get from the ADC with the value that corresponds to 2V, if higher then run the motor, if lower then stop it, you can figure that out. You may need to introduce some hysteresis around the threshold.

    Then send the value to the PC using the PBP's SEROUT command, or even better use the USART, a MAX232 level shifter and the HSEROUT command, see the manual. There's many examples on the forum.

    For the PC/VB side have a look here: http://www.rentron.com/VisualBasic.htm
    Just send the raw value from the PIC and use VB to scale it to volts if you like.

    /Henrik Olsson.

  31. #31
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Post Problem

    I had try the program that you gave me. It is work.Thank.
    Some problem has finding out....



    ***********'Produce squarewave on PortB.0 period~4.32s, 50% dutycycle.

    Loop var Word

    Main:
    High PortB.0
    For Loop = 0 to 2160 'Loop here for ~2.16s, tweak to match.
    PauseUs 1000
    Next
    Low PortB.0
    For Loop = 0 to 2160 'Loop here for ~2.16s, tweak to match.
    PauseUs 1000
    Next
    Goto Main**********

    The above is the code that you posted to me. Thanks to you again.
    I had modify it like the code below:-

    ********'Produce squarewave on PortB.0 period~4.32s, 50% dutycycle.

    Loop var Word
    SolarVoltage var word
    ADCON1 = %10001110

    Main:

    High PortB.0
    For Loop = 0 to 2160 'Loop here for ~2.16s, tweak to match.
    PauseUs 1000
    ADCIN 0,SolarVoltage
    LCDOUT $FE,$1,#SolarVoltage
    If SolarVoltage = 300 then
    high motor ' motor stop
    ELSE
    low motor ' motor run
    ENDIF
    If update = 1 then
    LCDOUT $FE,$C0,DEC2 Hour,":",DEC2 Minute,":",DEC2 Second
    ENDIF
    Next
    Low PortB.0
    For Loop = 0 to 2160 'Loop here for ~2.16s, tweak to match.
    PauseUs 1000
    ADCIN 0,SolarVoltage
    LCDOUT $FE,$1,#SolarVoltage
    If SolarVoltage = 300 then
    high motor ' motor stop
    ELSE
    low motor ' motor run
    ENDIF

    If update = 1 then
    LCDOUT $FE,$C0,DEC2 Hour,":",DEC2 Minute,":",DEC2 Second
    ENDIF
    Next
    Goto Main

    ON INTERRUPT
    '
    'Time calculation
    '
    '
    Update = 1 'update diaplay after 1 second*************


    The display: ****************
    0 ' when increase the A/D input, the value
    00:00:00 'increase to 0 then 1 then 2 then
    **************** 'maximum is 3

  32. #32
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Yes, you are correct, that will never work.

    A couple of things.

    1) The timing to produce the pulses to the motor is depending on the For Next loop and the PauseUS. When you insert a whole lot of other commands in there the timing will be WAY off. For example, the ADCIN alone will take at least 50uS, remember the DEFINE ADC_SAMPLEUS 50 then comes the LCDOUT which will take a "lot" of time also.

    Do you need the LCD to update 1000 times / second? That is what it's trying to do since you put it inside the FOR-NEXT loop.

    2) It is the For Next loop that pulses the step line to the motor. What are you trying to do with the high motor, low motor? Do you have an enable signal to the motordriver that is mapped to motor

    3) There's code missing in the INTERRUPT routine and the ON INTERRUPT statement should be at the beggining of the program with a LABEL telling it where to jump when an interrupt occurs.

    4) The ADC DEFINES are missing.

    5) The TRIS register set-up are missing.

    6) The motor variable(??) declaration is missing.

    7) You are checking if the SolarVoltage varible is equal to 300, so even if all the rest where OK the motor would only run when the value was exacly 300. You need to check if it's higher than 300.


    This is probably not the best way to this now that you are adding more and more stuff to it but it may get you going if you have decided to go this route instead of the interrupt and tick counting we also showed you.

    Again, this is completely untested! You will probably need to tweak the 2160 value in the For Next loop a little bit to get the correct timing.
    Code:
    Loop var Word                     'Loop variable for the FOR-NEXT loop
    SolarVoltage var word           'Raw value from ADC
    RunMotor var bit                  'Enable bit for step pulse routine.
    
    DEFINE ADC_BITS 10             'Set ADC to produce 10bits
    DEFINE ADC_CLOCK 3            'Set ADC clock to internal RC
    DEFINE ADC_SAMPLEUS 50     'Set conversion time to 50uS
    
    TRISA.0 = 1                         'Set RA0 (pin2) to input.
    TRISB.0 = 0                         'Set RB0 as output, step pulse to motor.
    ADCON1 = %10001110           'Set RA0 to analog, internal Vref, result right justified. (See datasheet)
    
    RunMotor = 0                       'Do NOT run motor
    
    Main:
    '//The IF statement here checks the flag to determine if the motor should be run or not.
    '// If it should be run the For-Next loop is executed.
    If RunMotor = 1 then                     'Produce pulses ONLY if supposed to....
      High PortB.0
        For Loop = 0 to 2160                 'Loop here for ~2.16s, tweak to match. 
          PauseUs 1000
        Next
        Low PortB.0
        For Loop = 0 to 2160                 'Loop here for ~2.16s, tweak to match. 
          PauseUs 1000
        Next
    Endif
    
    ADCIN 0, SolarVoltage                      'Get value from solarPV
    LCDOUT $FE,$1,#SolarVoltage           'Display value on LCD
    
    '// Here you can insert the code for sending to PC //
    '// and the LCD code for the time, if that's what your doing //
    
    If SolarVoltage > 300 then                'We are over the thershold
       RunMotor = 1                               'so lets enable the step pulses
       Goto Main                                   'and start over
    Else
      RunMotor = 0                                'disable the ste pulses.
    
    '// Since the For-next loop that produces the step pulses is not running now we insert a pause here.
    '// Otherwise the ADCIN and LCDOUT statements will execute VERY often. 
      For Loop = 1 to 1000                     
       PauseUs 1000
      Next
    
    Goto Main
    When you post code please include comments so that it's easier for us to understnad what you're trying to do. Also, please see the vbCode page here: http://www.picbasic.co.uk/forum/misc.php?do=bbcode for how to post code so that it shows in a window like above.

    /Henrik Olsson.
    Last edited by HenrikOlsson; - 14th December 2006 at 08:57.

  33. #33
    Join Date
    Nov 2006
    Posts
    33


    Did you find this post helpful? Yes | No

    Default same question again eeprom finish

    If I doesnt want to use external eeprom and I had used up all the internal eeprom space. As I know there was a way to store the data in the program like below:-

    asm:
    da:1,2,23
    endasm

    I do not familiar with this could any one one lead me thru this method? Thank
    I just want to store 200 data in there.

    Thanks

Similar Threads

  1. Pin won't stay high during Repeat...Until loop??
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 16th August 2009, 23:57
  2. Won't go back to SLEEP after 1st Interrupt
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 32
    Last Post: - 29th June 2009, 09:00
  3. Battery powered applications
    By NavMicroSystems in forum Off Topic
    Replies: 7
    Last Post: - 22nd June 2009, 07:12
  4. COUNT is not counting again
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 33
    Last Post: - 19th June 2009, 04:52
  5. Can't ID interrupt source with this IntHandler??
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 3rd June 2009, 02:35

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts