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.

HT12D and HT12E encoder/decoder issues

Status
Not open for further replies.
Well, now that that's cleared up - NOT.

I suppose what you typed is as clear as it is in your head...you have a long way to go yet.
 
Maybe I typed to fast WAY back on post "82 about the description of what I want to do.
Apparently you just take it like I am an idiot. Sure your more knowledgeable in this format but I wonder if you even read my descriptions?
After 20 posts you figured out what and why I want to do on this project.
As far as a long way to go, yes I need to sort out and get the code sections I have working all in one package.
 
Forget I said anything. Including helping you with the shift module and figuring out the HLVD module for you.
 
I have thanked you on numerous, Tried ALL your suggestions except the one on post #88
Have stated in public and in a PM that I look forward to your advice and have thanked you for your advice.
In fact I have rebuilt a perf board and running the HLVD code you posted, trying to reconfigure a way to get the RED led on for low battery and green on for good battery, all happens AFTER a button press.
Got it working but not as well as I would like. playing with the idea of masking the last four bits then changing them in code but havn't decided if its a good plan or just a train wreck waiting on the tracks.
 
Code now works with battery test etc.

The code needs some more work but it runs fairly smooth. I received the tilt switch samples but the data sheet states on the one to use a filter (Vcc/4.7meg in parallel w/ 10-100pf cap / 100k resistor/ switch/ground.
This setup was very buggy. Tried several different caps etc. but when tilting it would trigger all by itself. The second samples work very well. Kinda slow(damped w/ silicon oil) but very resistance to shaking.
The code uses a portB interrupt for tilt detection and detecting the s3 switch for testing the battery(works very well, just need to refine for 3v). Battery draw is .o4ma when asleep. Need to add the TX power enable and the HT12E to the mix.
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2013 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 1/2/2013                                                       *
*  Version : 1.0                                                            *
*  Notes   :  this one works 1/10/2013                                                              *
*          :                                                                *
*****************************************************************************
}



Device = 18F2420
Clock = 8
Config   LVP = OFF, mclre = off
Include "InternalOscillator.bas"
Include "utils.bas"
Dim RBIF As INTCON.0  //port change interupt flag
Dim RBIE As INTCON.3 //port change interupt enable
Dim x As Byte

Dim led0 As PORTC.3 // blue
Dim LED1 As PORTC.4  //green
Dim led2 As PORTC.5  //red
Dim s1 As PORTB.6
Dim s2 As PORTB.5
Dim s3 As PORTB.4
'xxxxxxxxxxxxxxxxxxxx
'interrupt
'xxxxxxxxxxxxxxxxxxxxx
Interrupt PORTB_Change()
 Save(0) // Save the system variables
 If RBIF = 1 Then // Check if the interrupt was a PORTB change
 //RBIF = 0  ' moved to end
 WREG = PORTB // Be sure to read the contents of PORTB to
 // clear the mismatch
 
 // PORTB 7:4 has changed
 If s1 = 0 Then 
 RBIF = 1
 LED1 = 1
 For x = 0 To 5
 
 led2 = 0
 led0 = 0
      DelayMS(500)
      Toggle (LED1)
      DelayMS(500)
      Toggle (LED1)
      Next
      LED1 = 0
     
 End If
 If s2 = 0 Then 
 RBIF = 1
 led2 =1
  For x = 0 To 5
   LED1 = 0
   led0 = 0
      DelayMS(500)
      Toggle (led2)
      DelayMS(500)
      Toggle (led2)
   Next
   led2 = 0
 End If 
 
 if s3 = 0 and  PIR2.bits(2)=1 Then         // check hlvd flag
   for x = 0 to 5
    led0 = 1     //blue
    DelayMS(500)
    toggle(led0)
    delayms(500)
    next
    pir2.bits(2)=0
 EndIf
    if pir2.bits(2)=0 then
    led1 = 1
    delayms(500)
    toggle(led1)
 endif  
 
 
 
EndIf

RBIF = 0      // clear flag  this changed from 3x to 2x
// Restore // Restore the system variables
 // WREG = PORTB // Be sure to read the contents of PORTB to
 // clear the mismatch
Restore
End Interrupt


 
Sub PORTB_Interrupts(Control As Boolean) // Small routine to enable/disable PORTB Interrupts.
 If Control = True Then 
 RBIE = 1 //  interrupt enable bit
 Enable(PORTB_Change)
  
 Else //
 
 RBIE = 0 //
 Disable(PORTB_Change) //
 EndIf //
End Sub
 
Inline Sub Sleep()
 Asm
    Sleep
 End Asm
End Sub

SetAllDigital
Input(s1)
Input(s2)
Input(s3)
output(led0)
output(led1)
output(led2)
HLVDCON = %00011000  // 3.39 volts change bit 7 for testing the HLVD
PIR2.bits(2)=0       // clear HLVD flag
PIE2.bits(2) = 1      //enable HLVD interrupt

// Start Of Program...
TRISB = %11110000 // Make PORTB7:4 all inputs
TRISC = %00000000 // Make PORTC all outputs
led0 = 0          // turn off all leds
LED1 = 0
led2 = 0

 
While True // Infinite loop
       
PORTB_Interrupts(True) // Enable PORTB interrupts
    Sleep // Put the PIC to sleep and wait for a change
 // on PORTB 7:4
Wend
 
You using on of these SQ-SEN-200 ?

Mrdeb you don't want all this in here
Code:
'xxxxxxxxxxxxxxxxxxxx
'interrupt
'xxxxxxxxxxxxxxxxxxxxx
Interrupt PORTB_Change()
 Save(0) // Save the system variables
 If RBIF = 1 Then // Check if the interrupt was a PORTB change
 //RBIF = 0  ' moved to end
 WREG = PORTB // Be sure to read the contents of PORTB to
 // clear the mismatch
 
 // PORTB 7:4 has changed
 If s1 = 0 Then 
 RBIF = 1
 LED1 = 1
 For x = 0 To 5
 
 led2 = 0
 led0 = 0
      DelayMS(500)
      Toggle (LED1)
      DelayMS(500)
      Toggle (LED1)
      Next
      LED1 = 0
 
 End If
 If s2 = 0 Then 
 RBIF = 1
 led2 =1
  For x = 0 To 5
   LED1 = 0
   led0 = 0
      DelayMS(500)
      Toggle (led2)
      DelayMS(500)
      Toggle (led2)
   Next
   led2 = 0
 End If 
 
 if s3 = 0 and  PIR2.bits(2)=1 Then         // check hlvd flag
   for x = 0 to 5
    led0 = 1     //blue
    DelayMS(500)
    toggle(led0)
    delayms(500)
    next
    pir2.bits(2)=0
 EndIf
    if pir2.bits(2)=0 then
    led1 = 1
    delayms(500)
    toggle(led1)
 endif  
 
 
 
EndIf
 
RBIF = 0      // clear flag  this changed from 3x to 2x
// Restore // Restore the system variables
 // WREG = PORTB // Be sure to read the contents of PORTB to
 // clear the mismatch
Restore
End Interrupt

That don't make any sense.
The processor responds by suspending its current activities, saving its state, and executing a small program called an interrupt handler (or interrupt service routine, ISR) to deal with the event.

You have most of your whole program in there.
 
Last edited:
Thats what I ended up with

It seems to work well but maybe it could work more efficiently. I tried using an EVENT but couldn't get it to work. Going to retrace my steps and find maybe a better method?
Tried a SQ-SEN 645B but found a 4001-1000 from SELECT Controls works better. I have two damped ones and two UN-damped ones. Have yet to try the UN-damped units.
The ISR I have mixes the tilt switch routine with the battery test routine all in one package. wanted to avoid more than two ISR. Weather its a good idea or not?
Also not sure if leaving the SAVE and RESTORE intact. Didn't seem to make and difference saving the system variables. Going to make a few changes including any suggested changes.
I tried your posted suggestion but it didn't do what I was after.
Unit is placed on a table, button pressed to indicate battery condition. Button press enables the TX power ON and enables the HLVD routine then enables either a green LED or RED led. This to hopefully eliminate overcharging of batteries. Am still contemplating adding an audible signal when batteries are getting low while in use. Still need to add audible alert indicating unit is transmitting data to the Decoder/Matrix unit.
Thanks to Jon, Tumbleweed and Burt I have gotten this far. Hopefully didn't forget anybody?
 
Weather its a good idea or not?
Ok guess our on your own now.
But you may as well not even use a interrupt. Your running your whole code in there no need to worry about saving anything.
 
I need the interrupt to be able to put the PIC to sleep?? Remember this is battery powered.
In you professional opinion, do you think an interrupt is needed or? I looked at EVENT as you suggested several posts ago and tomorrow I am going to look further into the EVENT.
I need suggestions not solutions. Its more fun discovering how this stuff works. As for two interrupt routines, I understand it could have a conflict or ??
I found using the portB interrupt on change works so I just threw the battery test into the mix. Good idea or ??
 
It's wrong how you have it and the pic is never going to sleep If you look at your complied code sleep never happens

You have all your code in the interrupt and delays you turned it into a main loop all that should be there is a few lines to see what caused it and then return to your main code.

This would be in the ISR
Code:
Like if PORTB not PORTB then find the change  reset the interrupt jump to run needed code in main
Then if every thing stops let's take a nap and sleep and wait for the PORTB change to wake use up.

Now the HLVD only works one way if you set for a low voltage and use a interrupt it says that way till you reset the chip which make good sense batteries low you need to change them which would reset the chip anyways.

Now if you poll it Like Jon code you can do a lot more with it easy but the chip can't poll it while asleep.
which means if your batteries are going dead and it's sleeping you'll not no but if any one who used this didn't test it to see if it's working before they ride there bike is not very bright. I mean come on I hit the button and the dang lights don't work oh I need to test the batteries O that don't work are they dead come on lets go to wallmart and get new ones, or the dollar store and get cheap one's.

This part is a joke dry but still a joke
Which while were here let's find a better bike light cause mine is broke the test battery switch don't work
and i can't tell if there dead. Why are they saying that is not battery tester for testing a battery?

How's yours work when there dead
 
Last edited:
Like my clock when the power goes off the battery keeps it running but it blinks to let you no the idea is back up

But with this the idea should be check your light to see if the work test battery to see if it's charged
 
The only interrupt you need is the interrupt to wake up the micro when a button is pressed.
 
You'd be we'll served to simplify your code. Here's a brief snippet that is needlessly complex and confusing.

Code:
If s1 = 0 Then 
 RBIF = 1
 LED1 = 1
 For x = 0 To 5
 
 led2 = 0
 led0 = 0
      DelayMS(500)
      Toggle (LED1)
      DelayMS(500)
      Toggle (LED1)
      Next
      LED1 = 0
 
 End If

Consider what happens if S1 is pressed (0):

LED1 is turned on

Enter a 5 step FOR / NEXT loop.

Delay 500 mS

LED1 is toggled (now it's off)

Delay 500 mS

LED1 is toggled again (now it's on)

Repeat the loop 5x.

LED1 is turned off.


The toggle command turns the LED off if it's on and on if it's off.

Better would be:

Code:
For I = 1 to 10
    Toggle (LED1)
    Delayms(500)
Next
LED1 = 0

In this alternative, the LED is flashed on & off 10x. There is no need to turn it on initially because it's off to start with. It's turned off at the end just to be safe, even though after toggling 10x, it should already be off.

Eight lines of code have been replaced by five lines that are more clear. It may work either way but it takes more code space, it's more difficult to follow and troubleshoot. There's no need to have two toggle commands in a loop as toggle is alternate action.
 
processing in ISR, all other intterupts are disabled temporarily. For this same reason, you want to keep your ISR as short as possible (to avoid messing with the system clock itself

If you look at your code you have 3.5 seconds of delays In the interrupt.
 
In my posted code, the PIC does go to sleep. How do I know that you ask?
I inserted an LED blink routine in the WHILE WEND loop and had a meter connected to the circuit. The LED blinked for 2 seconds then the circuit started drawing .04ma.
Jon pointed out several flaws in my code which I plan to institute. I knew the code wasn't perfect by a long shot. Lets call it a work in progress.
After I post this I am going to study and make some changes to my code and as Burt pointed out I have too many delays in the interrupt(3.5seconds? I need to look and find out how you figured that out. Maybe all the delays I have spread all over the code). Maybe that's why sometimes the tilt switch doesn't respond quickly but I felt it might be the oil inside the switch.
THANKS GUYS
 
YES I over did it on the toggle statements.
As I have it the PIC goes to SLEEP between switch closures (RIGHT TURN, LEFT TURN) and wakes up when ever a switch is closed. Same holds true for the battery test but during the test the transmitter is powered on and the HLVD routine is instituted. I need to add the TX power enable to the code.
This code is a combination of different sections of example code. Each section (HLVD, Turn switches and the HT12D chip) was tested by itself than put into one code. My first two attempts were a train wreck of massive proportions.
I learned a few things along the way. Am glad I remembered about inserting an LED here and there to check code flow. Works great!
 
...and as Burt pointed out I have too many delays in the interrupt(3.5seconds? I need to look and find out how you figured that out. ...

This isn't magic. Just follow the path through the code and add up the delays. Burt was actually a little short.

Any time a switch is pressed, you have a 5 step FOR/NEXT loop where you flash an LED for half-second on and half-second off -

5 loops x (500mS delay + 500 mS delay) = 5 seconds.

Keep in mind...a delay statement means everything stops dead for that period of time.

I added comments in the code to show you these delays.

Code:
Interrupt PORTB_Change()
 Save(0) // Save the system variables
 If RBIF = 1 Then // Check if the interrupt was a PORTB change
 //RBIF = 0  ' moved to end
 WREG = PORTB // Be sure to read the contents of PORTB to
 // clear the mismatch
 
 // PORTB 7:4 has changed
 //************************************************************ First possible path
If s1 = 0 Then 
 RBIF = 1
 LED1 = 1
 For x = 0 To 5                  //************************** five loops
 
 led2 = 0
 led0 = 0
      DelayMS(500)             //**************************  500 mS delay
      Toggle (LED1)
      DelayMS(500)            //**************************  500 mS delay
      Toggle (LED1)
      Next                          // 5 loops * (500 mS + 500 mS) = 5 seconds!
      LED1 = 0
 
 End If
 //************************************************************ Second possible path

 If s2 = 0 Then 
 RBIF = 1
 led2 =1
  For x = 0 To 5                              //************************** five loops   
   LED1 = 0
   led0 = 0
      DelayMS(500)                         //**************************  500 mS delay
      Toggle (led2)
      DelayMS(500)                        //**************************  500 mS delay
      Toggle (led2)
   Next
   led2 = 0
 End If 
  //************************************************************ third possible path

 if s3 = 0 and  PIR2.bits(2)=1 Then         // check hlvd flag
   for x = 0 to 5                                         //************************** five loops
    led0 = 1     //blue
    DelayMS(500)                                      //**************************  500 mS delay
    toggle(led0)
    delayms(500)                                      //**************************  500 mS delay
    next                                                     // 5 loops * (500 mS + 500 mS) = 5 seconds!
    pir2.bits(2)=0
 EndIf
    if pir2.bits(2)=0 then
    led1 = 1
    delayms(500)
    toggle(led1)
 endif  
 
 
 
EndIf
 
RBIF = 0      // clear flag  this changed from 3x to 2x
// Restore // Restore the system variables
 // WREG = PORTB // Be sure to read the contents of PORTB to
 // clear the mismatch
Restore
End Interrupt
 
 
 
Sub PORTB_Interrupts(Control As Boolean) // Small routine to enable/disable PORTB Interrupts.
 If Control = True Then 
 RBIE = 1 //  interrupt enable bit
 Enable(PORTB_Change)
 
 Else //
 
 RBIE = 0 //
 Disable(PORTB_Change) //
 EndIf //
End Sub
 
I studied what I had and YES I counted up all the delays. Can't believe how carried away I got --lol
In my hopefully final code I will not even have the LED1 and LED2 only just a quick 2ms delay, just enough for the HT12E to send the right or left data stream. I only used the blinking LED to tell me that I have a proper switch depression. I will need to have another look at the data sheet but I might be able to get away with a DELAYUS?
I found another glitch in my code where it was falling through and blinking an LED that was not supposed to blink.
Them LEDs really help in following code flow. As an example, I found the pic was only going to SLEEP on the first run through. FIXED and now it goes to SLEEP after every button press, THANKS to them LEDs.
 
GOT it ALL working!!

I cleaned up the code, got ride of alot of delays, the HLVD routine was giving me trouble but I found I had an END IF in the wrong place.
connected a green LED for GD_bat(good battery) and the blue LED (led0) for a low voltage or batteries need recharging.
I discovered I can alter the circuit voltage for checking the HLVD by changing the voltage in MPLAB next to the MCLR box. The HLVD works pretty good but thinking maybe have it trigger an audiable beep wile in use if the battery gets to low. Would be a nice feature. Any thoughts on this?
well here is my present code.THANKS to Jon for pointing out all my unneeded routines(lines of code).Burt mentioned I had too much down time or delays as well. Code runs better or it seems to. Now to connect the two tilt switches and determine angle at point of switch closure.
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2013 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 1/2/2013                                                       *
*  Version : 1.0                                                            *
*  Notes   :  this one works 1/10/2013                                                              *
*          :                                                                *
*****************************************************************************
}



Device = 18F2420
Clock = 8
Config   LVP = OFF, mclre = off
Include "InternalOscillator.bas"
Include "utils.bas"
Dim RBIF As INTCON.0  //port change interupt flag
Dim RBIE As INTCON.3 //port change interupt enable
Dim x As Byte
dim TX_Enable as portc.0
dim TX_pwr as portc.1
dim GD_bat as portc.2
Dim led0 As PORTC.3 // blue
Dim LED1 As PORTC.4  //green
Dim led2 As PORTC.5  //red
Dim s1 As PORTB.6
Dim s2 As PORTB.5
Dim s3 As PORTB.4
'xxxxxxxxxxxxxxxxxxxx
'interrupt
'xxxxxxxxxxxxxxxxxxxxx
Interrupt PORTB_Change()
 Save(0) // Save the system variables
 If RBIF = 1 Then // Check if the interrupt was a PORTB change
 //RBIF = 0  ' moved to end
 WREG = PORTB // Be sure to read the contents of PORTB to
 // clear the mismatch
  // PORTB 7:4 has changed
'xxxxxxxxxxxxxxxxxxxxxxxxxxx
//                          TURN DETECTION
'xxxxxxxxxxxxxxxxxxxxxxxxxx
'   LEFT
'--------------------
 If s1 = 0 Then 
    RBIF = 1
    LED1 = 1  // GREEN       // NOTE I need to make ports LOW for transmission, HIGH for testing
    led2 = 0
    led0 = 0
    TX_pwr = 1               // turn on transmitter
    TX_Enable = 0            // enable encoder
         DelayMS(500)
    Toggle (LED1)
         delayms(500)
    LED1 = 0      // make sure its off
    tx_pwr = 0
    TX_Enable =1           // LOW for transmit        
      
       
 End If
      
 '-------------------------    
'    RIGHT
'--------------------------
 If s2 = 0 Then 
    RBIF = 1
    led0 = 0
    LED1 = 0
    led2 = 1    // RED
    TX_pwr = 1               // turn on transmitter
    TX_Enable = 0            // enable encoder
           DelayMS(500)      // just enough to see for testing
    Toggle (led2)
           delayms(500)
    led2 = 0     // make sure its off
    tx_pwr = 0
    TX_Enable =1           // LOW for transmit        
 End If 
    
'xxxxxxxxxxxxxxxxxxxxxxxxxx
//                         BATTERY TEST 
'xxxxxxxxxxxxxxxxxxxxxxxxxxx
' BAD BATTERY
 if s3 = 0 and  PIR2.bits(2)=1 Then         // check hlvd flag
    TX_pwr = 1    //turn on transmitter
    led0 = 1     //blue led next to green BI color in final plan
         DelayMS(1000)
    toggle(led0)
 end if
    PIR2.bits(2)=0
     
 ' GOOD BATTERY
 if s3 = 0 and pir2.bits(2)=0 then
       GD_bat = 1       // green led next to blue GD_bat = good battery
       delayms(1000)
       toggle( GD_bat)
       delayms(1000)
       TX_pwr = 0                       //turn off transmitter
    endif  
    pir2.bits(2)=0    // reset interrupt flag  DO I REALLY NEED TO RESET?
 EndIf
 

RBIF = 0      // Port change interrupt flag bit

Restore
End Interrupt


 
Sub PORTB_Interrupts(Control As Boolean) // Small routine to enable/disable PORTB Interrupts.
 If Control = True Then 
 RBIE = 1 //  interrupt enable bit
 Enable(PORTB_Change)
  
 Else 
 
 RBIE = 0 //  port change interrupt enable bit
 Disable(PORTB_Change) //
 EndIf //
End Sub
 
Inline Sub Sleep()
 Asm
    Sleep
 End Asm
End Sub

SetAllDigital
Input(s1)
Input(s2)
Input(s3)
output(led0)
output(led1)
output(led2)
output(TX_Enable)
output(TX_pwr)
output(GD_bat)
HLVDCON = %00010111  // 3.12 volts
PIR2.bits(2)=0       // clear HLVD flag
PIE2.bits(2) = 1      //enable HLVD interrupt



// Start Of Program...
TRISB = %11110000 // Make PORTB7:4 all inputs
TRISC = %00000000 // Make PORTC all outputs
led0 = 0          // turn off all leds
LED1 = 0
led2 = 0
TX_Enable = 1
TX_pwr = 0
GD_bat=0 
While True // Infinite loop
       
PORTB_Interrupts(True) // Enable PORTB interrupts
    Sleep // Put the PIC to sleep and wait for a change
 // on PORTB 7:4
Wend
 
TOGGLE is designed to toggle a port pin....high, low, high, low, high, low. Why use it if you're just turning an LED on for a moment and off.

LED = 1

Delayms(x)

LED = 0

Is much more clear as to intent and should result in much less code being generated by the compiler.

And as Burt has said several times, the interrupt subroutine should have the minimal amount of code within. Set a status flag to left, right, whatever...and act on it in main program loop. Having many program steps in the interrupt routine can (and will) lead to unreliable operation.
 
Status
Not open for further replies.

Latest threads

Back
Top