Menu

Working on an lm 35 temp sensor

Judah Ben
2019-11-19
2019-12-06
<< < 1 2 3 > >> (Page 2 of 3)
  • Judah Ben

    Judah Ben - 2019-11-20

    Sorry for the confusion.
    That was formerly:

    main program:
    ;other display code
    On interrupt PORTB.0change call ok
    loop
    
    sub ok
    on interrupt PORTB.0change call save
    on interrupt PORTB.1change call down
    on interrupt PORTB.2change call up
    end sub
    

    I later changed that to the above since the code did not compile.

    What I intend for the project is this:
    The menu is to come up when the reference temperature needs to be adjusted (the menu should be called by the 'ok' switch).
    The reference temperature is to be saved so it can remain the same even when the system restarts except it is changed. (the save is also carried out by the ok switch but only when the menu is called out already).
    This reference temperature can then be used to set conditions for maybe a fan or a heater and stuff.

     
  • Anobium

    Anobium - 2019-11-21

    OK. Sort out the interrupt first.

    The 877a has the following interrupt capability (for this port). PORTBChange

    So, your code will be On interrupt PORTBChange call MyISRHandler

    Then, in your new sub called MyISRHandler you need to determine the source of the interrupt - which port raised the interrupt. Then, you can set a variable ( a state variable ) and exit. Then, in your main program examine state variable to update the LCD.

    Do not try to updated the LCD within the interrupt handler - this will lead to many issues. If you do... the LCD will be updating very nicely and you will be missing all the other events... So, keep the interrupt handler very short.

    Hope this helps.

     
  • Judah Ben

    Judah Ben - 2019-11-21

    Thanks a lot.
    I'll try it.

     
    • Anobium

      Anobium - 2019-11-21

      I have probable missed that you may have to clear the event in the handlers, and/or to raise the event per port you may have to set a specific bit. This will all be in the datasheet.

       
  • Judah Ben

    Judah Ben - 2019-11-21

    Uhmm.... I'll see how I can do that though I must say that the datasheet is a bit confusing.

     
  • Anobium

    Anobium - 2019-11-21

    Page 44. Four of the PORTB pins, RB7:RB4, have an interrupton-change feature. Only pins configured as inputs can cause this interrupt to occur (i.e., any RB7:RB4 pin configured as an output is excluded from the interrupton-change comparison). The input pins (of RB7:RB4) are compared with the old value latched on the last read of PORTB. The “mismatch” outputs of RB7:RB4 are OR’ed together to generate the RB port change interrupt with flag bit RBIF (INTCON<0>)

    So, set the interrupt and test the Port. As at least one of the RB7:RB4 pins changed state; a mismatch condition will continue to set the bit. Reading PORTB will end the mismatch condition and allow the bit to be cleared.

     
  • Judah Ben

    Judah Ben - 2019-11-21

    Hello, Anobium.
    I've tried working on the code while looking at the datasheet and comparing with a sample demo (keypad demonstration with hardware serial).
    Here's what I came up with.
    It compiles but it does nothing on the simulation.
    I've attached the gcb and asm files also.

    #chip 16f877a, 4
    
    #option explicit
    
    #config osc=XT
    #config WDT = OFF
    
    #define sensor PORTA.5
    #define up PORTB.6
    #define down PORTB.5
    #define ok PORTB.4
    
    ;lcd connection settings
    #define LCD_Speed medium
    #define LCD_IO 4
    #define LCD_NO_RW
    
    #define LCD_RS PORTD.2
    #define LCD_Enable PORTD.3
    #define LCD_DB4 PORTD.4
    #define LCD_DB5 PORTD.5
    #define LCD_DB6 PORTD.6
    #define LCD_DB7 PORTD.7
    
    dir sensor in
    dir up in
    dir down in
    dir ok in
    
    dim tempnow as Word
    dim ccount as Word
    dim tempold as word
    dim tempref as word
    dim IOCB4 as Bit
    dim IOCB5 as Bit
    dim IOCB6 as Bit
    dim tempref1 as word
    
    ;variables used
    ccount=0
    print "System On..."
    wait 3 s
    cls
    Print "Obtaining temp."
    wait 2 s
    locate 1,0
    print "Please wait...."
    wait 2 s
    cls
    
    'init tempold so it not equalt tempnow, if can never read 65535
    tempold=0xffff
    
    
    main:
    do forever
    
    dim tempnow as Word
    tempnow=scale(ReadAD10(AN4),0,1023,0,499)
    
    on interrupt PORTBchange call MyISRhandler
    
    tempref=tempref1
    
    if tempold<>tempnow then
    cls
    print tempnow
    print " degrees C"
    tempold=tempnow
    ccount++
    end if
    
    wait 10 ms
    
    sub MyISRhandler
    if IOCB4=1 then call ok
    end sub
    
    sub ok
    
    cls
    print "Adjust ref temp."
    EPRead EEADR, tempref
    locate 1, 0
    print tempref1
    if IOCB5=1 then call down
    end if
    if IOCB6=1 then call up
    end if
    if IOCB4=1 then call save
    end if
    goto main
    
    end sub
    
    
    sub down
    tempref--
    end sub
    
    sub up
    tempref++
    end sub
    
    sub save
    intoff
    EPWrite EEADR, tempref
    inton
    end sub
    
    
    loop
    
     
  • Anobium

    Anobium - 2019-11-21

    A few changes.... I cannot test but it should work.

    Sub up, down and save... I am not sure what is happening but I have renamed.
    Look at the interrupt - now. It is short. It sets a variable. I was not clear - calling the sub from the ISR hanlder extends the time to complete the subs... so, short is goodness.

    Then, I added a Select-Case. Seems an easy to test what happened in the ISR. You have had a lot of IF-THEN.. like eventvalue.6., eventvalue.5, eventvalue4 but the select looks nice.

    You have all the code with in the loop. An odd approach. So, I have moved the loop and got rid of the goto.

    Your bits. Not sure what they were doing. Not needed me things. So, gone.

    See what happens.

     
  • Judah Ben

    Judah Ben - 2019-11-21

    Okay, let me re-run.
    I'll try to understand what's going on also.

     
  • Anobium

    Anobium - 2019-11-21

    Just thinking.... this will be smarter looking!

    ....
    ....
    if tempold<>tempnow then
            LCDhome
            LCDSpace 16
            LCDhome
            print tempnow
            print " degrees C"
            tempold=tempnow
    ...
    ...
    
     
    • Judah Ben

      Judah Ben - 2019-11-21

      Oh, I just saw this.

       
  • Judah Ben

    Judah Ben - 2019-11-21

    While I ran the code, here are a few things I noticed:
    1. The lcd constantly goes from 0-9 and starts again even for continous increase in temperature from the sensor.
    2. The buttons don't work yet.
    I saw the comment where you defined IOCB4 to IOCB6 as bit and I fhought it was meant to be a definition so I removed the apostrophe(after I tried with it on)
    I should've responded earlier but I tried to accustom myself to the new stuff I saw such as the string, pad, and the select case condition to the extent to which I could.

    I must say that I'm a bit stuck at this point.
    I'm quite at a loss on what to do.
    I'll really appreciate any pointers at all.
    I'll try to attach the gcb file with the little corrections I made and my proteus simulation screenshot so far.

     
  • mmotte

    mmotte - 2019-11-21

    Judah,
    Anobium is probably getting some sleep.

    I have 2 observations
    1)The select case is a great tool. The values you are looking for are wrong? You have pullup resistor on the three buttons so when no buttons are pushed the port value should be 0$FF or binary b'11111111'. When "save" button is pushed , b'11101111' not 16. fix the values in the select.

    2)As the PIC16877A document says: in the Interrupt Service Routine, can clear theinterrupt in the following manner:a) Any read or write of PORTB. This will end themismatch condition.b) Clear flag bit RBIF.A mismatch condition will continue to set flag bit RBIF.Reading PORTB will end the mismatch condition andallow flag bit RBIF to be cleared..

    So how do you handle waiting for the pressed button to be released and portB be returned to 0$FF? then you can clear the interruprt after reading the port again. Now you interrupt again but nothing happens because you haven't reset the RBIF. If the release does interrupt again this may be ok because select case doesn't do anything for 0$FF.

    Maybe this would help.

    sub MyISRhandler
    
          eventvalue = PORTB
          RBIF = 0
      end sub
    

    GL
    Mike

     
    • Judah Ben

      Judah Ben - 2019-11-23

      Thanks a lot, Mmotte.

       
  • Anobium

    Anobium - 2019-11-22

    Oh yes... Pull Ups. I would not have spotted that. See attached. Essentially, the test for the bits is now a little more complex (only a tad more).

    See attached. I have added 'here' to show the three changes.

    So, now.... the bits 4,5,6 are, as Mike says, 0b01110000 which is d112. So, we know we need to examine the state of those three bits. To do this we AND the eventvalue as the other bits may have generated an event. We test to see if the three bits are High (to match the pullups). Then, we test the bits (I used decimal - you may want to use binary notation).

    But, Mike was 100% correct... the code is PULLUP, I assume PULLDOWN. But, we do not need to clear RBIF as the Great Cow BASIC handles this for you.

    So, have a look at the revised code.

     
  • Judah Ben

    Judah Ben - 2019-11-23

    I'm sorry for the late reply. I wanted to make sure I try to have a basic understanding of the parts of the code before continuing.

    Here's where I've some little issues:

    1. For the problem where the LCD was constantly moving between 0-9 for consistent increase in temperature form the lm35, I found out that it was the lcdhome command that was causing it. It began to correlate when I took out that command. I also couldn't leave in the "lcdspace 16" command because it just printed spaces and displayed nothing.

    2. I tried to use the 'case 96' which I think represents the ok button (even though I have no idea how it does. The cases weren't declared in the code above so I checked the datasheet to see if they were specific to IOC feature on this chip, still nothing) to call up the sub_save subroutine but I noticed two things:
      The string "saved" was always displayed when I clicked the ok button to save (I even removed it from the code to know where it was from and recompiled but it kept on being displayed, maybe it was saved or something).
      tempref was always at 20 (I don't know if it was saved at that and refused to change to the new value)

    3. The 'goto main' statement at the end of the sub_save routine doesn't work. The LCD remains at that menu.

    I've tried to read up a little on binary and hexadecimal to understand the initialization for portstatus.....Uhmm, little success.
    I've also tried fiddling with the code a little more. The code didn't compile so I'll try to attach the gcb file.

    Lastly, I'd appreciate any link to understand how to do debouncing to account for double presses.

     
  • Anobium

    Anobium - 2019-11-23

    :-)

    1. OK.
    2. 96 and the other values are the decimale value of a the binary notation. d96=0b1100000 . And, we need to know that your ports go low (remember you choose pulled high which does make this a lot harder to explain when compare to pulled low). So, we mask the port with the constant PortStatus. PortStatus is d112 or 0b01110000. So, we makes the port value as follows - for a moment except that the top three bits all pulled high and we going to ingore the rest.
      Where PortB = all high therefore 255.
      255 AND PortStatus returns 112 as all the bits (that we are interested) are high,

    So, where bit 4 is pushed low. So, the port would return
    239 AND PortStatus returns 96 as we have one bit low.

    We can use this method to determine the state of any port.

    All that said.... a much easy method to understand may be to use IF-THEN

              if tempold<>tempnow then
                cls
                print tempnow
                print " degrees C"
                locate 1,0
                print "Atmospheric temp"
    
                tempold=tempnow
                ccount++
              end if
    
              if ( eventvalue and PortStatus ) <> PortStatus then
    
                  If eventvalue.6 = 0 then
                          sub_down
                  end if
                  If eventvalue.5 = 0 then
                          sub_up
                  end if
                  If eventvalue.4 = 0 then
                          sub_ok
                  end if
    
                  'reset eventvalue
                  'here - this essentially reset the event flag
                  eventvalue=PortStatus
              else
                  wait 10 ms
                  locate 1, 15
                  Print " "
    
              end if
    
          Loop
    
    1. Do NOT use goto. You are exiting the DO-LOOP. Rethink your use of GOTOs. By doing the GOTO do not reset the eventvalue.

    2. See attached. Works in my SIM.

     
  • Anobium

    Anobium - 2019-11-23

    :-) When I say works... it does the basic. You will have to resolve issues like:
    1. Decrementing the value will overflow the variable and you can go from 0 to 65535.... so, you to stop that.
    2. LCD needs a tidy up.... a later. :-)

     
    • Judah Ben

      Judah Ben - 2019-11-27

      Hello, Anobium.
      Thanks for the help so far.

      I have been able to implement the circuit in hardware.
      My LCD was giving me flickering issues at first but after doing the following, I was able to get a somewhat stable display:
      * Adding a 100uf filtering capacitor to the LCD power supply.
      * Increasing the LCD speed to "fast".
      * Using a separate 7805 regulator for the LCD since it was dropping the PIC's 7805 to 3 plus volts.
      After these, the LCD became stable but for the temperature values which were so randomly changing between 150-350 so quickly even when the lm35 is connected.
      The lm35 still fails to output the expected temperature. It shares power supply with the pic which is 5 volts although this voltage drops to about 4.8 volts.

      The buttons don't bring up the menu except when pressed like two to five times and it's also random.
      For the up and down buttons to set a ref temp, it counts up to 65535 or so which seems strange.

      Overall, someone suggested I put in a higher frequency crystal oscillator like 6MHz. I'm yet to do that.

       
  • Anobium

    Anobium - 2019-11-27

    Well progress.

    Can you post your source? I can look at the code.

     
  • mmotte

    mmotte - 2019-11-28

    Here is your worst problem!

     sub MyISRhandler
    
              PulseOut PORTA.1, 200 ms
              eventvalue = PORTB
    
          end sub
    

    Anobium told you to make the interrupt handler very minimum amount of code. A 200 ms pulse is locking your micro in the interrupt for very long time. do not put the pulse out here.

     
    • Judah Ben

      Judah Ben - 2019-11-28

      Okay, thanks.
      I probably didn't get that. I was looking for a way to have a buzzer beep for every key press.
      It isn't even working yet.
      (I first   used
      'Set A. 1 on'
      'wait 200 ms'
      'set A. 1 off'
      didn't work too.)
      What should be the best place to put it the pulseout pls?

       
  • Anobium

    Anobium - 2019-11-28

    Morning,

    For a beep look up TONE in the Help. It does all the heavy work for you.

     
    • Judah Ben

      Judah Ben - 2019-11-28

      I came across tone but I thought since the buzzer I'm using is an active one that gives out a tone of constant frequency once powered, tone might have problems.
      I'll try it out

       
<< < 1 2 3 > >> (Page 2 of 3)

Log in to post a comment.