PDA

View Full Version : Code Problems with 16F684



Ryan7777
- 17th December 2010, 15:12
Hello and thanks for any and all help or comments,

I'm having issues with the attached code. Its for a circuit that replaces an Escort Radar Detector "Smart Cord". The original just didn't have enough features for me, so I built my own and tossed in a PIC to add a few more features.

The PIC for the most part adds a "flip-flop" type on-off function by inputing the state of a tact-button and toggling a relay and green power LED on or off when pressed between 100 mS and 1 S ( anti "accidental bump" protection).

When a radar alert is detected on another pin, the PIC flashes red and blue LEDs in an alternating fashion for a visual alert (very small and NOT visible outside of my car).

Another feature uses an ADC input to measure the voltage output by the cars dashboard light dimmer circuit to dim the LEDs in relation with the dashboard lights. Also, when the car detects that it is daylight out, it automaticaly turns the dashlights off and takes the dimmer voltage to ground which makes my radar detector cord LEDs go to full brightness so they can be seen in daylight. (Thanks HUGE to Darrel Taylor and his HPWM10 routine!)

The above all works fine, and is great. However, When I try to detect the length of the power button press to see if it is held down for more than ~ 3 seconds and toggle a bit which is suppsed to suppress the LEDs (turn them off, but leave the radar detector on), It doesn't work. As in it won't turn off the LEDs, But everything else still works.

I use a while/wend on the tact-button input pin to increment the variable "onOffBtntst" while the button is pressed. If it is pressed for 100 mS to 1 S then it toggles the power on and off like above. If it is held for more than 3 seconds it should set the varible "suprsLEDs" to 1 which in turn should keep the LEDs off. It doesn't seem to want to suppress the LEDs. The power on-off part works as expected, and if you hold the button for more than 1 S it doesn't toggle the relay, which it shouldn't. Maddning!

I then added a serial debug output to PORTC.4 to try to see what "onOffBtntst" is doing, and then what "suprsLEDs" is doing and that won't work either! It just spits gibberish into hyperterm (spades) and another program "realterm" (random giberrish), and I've tried every
mode PIC side and port setting on the PC side I can think of (Both program and hardware device settings. other serial devices work fine)

I think I must be setting up a port or module wrong or have a logic error that I just can't see. I've stepped away and came back over the past two weeks and still can't nail it down, Please
help!


@ DEVICE pic16F684,INTRC_OSC_NOCLKOUT, WDT_OFF, PWRT_OFF, MCLR_OFF, BOD_OFF, IESO_OFF, FCMEN_OFF

include "HPWM10.pbp"

DEFINE OSC 8 ' Define 8 MHz oscillator

DEFINE ADC_BITS 10 ' 10 bit A/D Conversion
DEFINE ADC_SAMPLEUS 50 ' 50 uS A/D sample time

CMCON0 = %00000111 ' Disable Comparator
VRCON = %00000000 ' Disable Comparator Voltage Reference

ANSEL = %01000000 ' Set pin 8 (AN6) to analog input, the rest to digital
ADCON0 = %10011001 ' Set up A/D converter - Right Just., VDD REF., CH 6, ON
ADCON1 = %00110000 ' Set up A/D Converter clock source to internal RC

TRISC.2 = 1 ' Set Pin 8 to input for A/D Converter input
TRISC.5 = 0 ' Set Pin 5 to output for PWM generator
TRISA.5 = 1 ' Set Pin 2 to input for Power ON/OFF Button
TRISC.3 = 0 ' Set Pin 7 to output for Power ON/OFF Relay
TRISA.4 = 1 ' Set Pin 3 to input for Power LED sense input
TRISA.3 = 1 ' Set Pin 4 to input for Alert LED sense input
TRISC.1 = 0 ' Set Pin 9 to output for LED3 - Blue Alert LED Cathode
TRISA.2 = 0 ' Set Pin 11 to output for LED2 - Red Alert LED Cathode
TRISA.0 = 0 ' Set Pin 13 to output for LED1 - Green Power on LED Cathode

' definitions

onOffBtn var PORTA.5 ' Power ON/OFF Button - Pin 2
onOffRly var PORTC.3 ' Power ON/OFF Relay - Pin 7
brghtns var PORTC.2 ' LED Brightness A/D input. - Pin 8
pwrOn var PORTA.4 ' Power LED sense input - Pin 3
alrt VAR PORTA.3 ' Alert LED sense input - Pin 4
LED1 var PORTA.0 ' LED1 - Green Power on LED Cathode - Pin 13
LED2 var PORTA.2 ' LED2 - Red Alert LED Cathode - Pin 11
LED3 var PORTC.1 ' LED3 - Blue Alert LED Cathode - Pin 9
beepSup Var PORTA.1 ' Beep Suppress - Pin 12
beep var PORTC.0 ' Beep on power cut - Pin 10
serial var PORTC.4 ' Serial out for debugging - Pin 6

btnVar var byte ' Holding variable for Power Button
aTOd var word ' Holding variable for A/D converter
Frequency var word ' Holding variable Frequency for PWM
DutyCycle1 Var Word ' Holding variable Duty Cycle For PWM
beepLoop var byte ' Loop Variable for beep
beepKill var bit ' Kill variable for beep loop
onOffBtnTst var word ' Test variable for on/off button
suprsLEDs var bit ' Variable to suppress LEDs

frequency = 1000 ' Set PWM frequency to 1000 Hz
LOW LED1 ' Set Green Power on LED to off at start-up
LOW LED2 ' Set Red Alert LED to off at start-up
LOW LED3 ' Set Blue Alert LED to off at start-up
low onOffRly ' Set On/Off relay to off at start-up
btnVar = 0 ' Clear On/Off Button Variable
aTOd = 0 ' Clear A/D converter Variable
DutyCycle1 = 0 ' Clear PWM Duty Cycle Variable
beepLoop = 0
beepKill = 0
onOffBtnTst = 0
suprsLEDs = 0
high beepsup

'-------------------------------------------------------------------------------
MainLoop:

button onoffbtn, 0, 255, 0,btnvar, 1, pwrOnOff:

PowerCheck_Alert:
IF pwron = 0 then
gosub pulseWidthModulator:
if suprsLEDs = 0 then
HIGH led1
else
LOW led1
endif
high beepsup
HIGH Beep
beepkill = 0
else
LOW led1
if onOffRly = 0 then
if beepkill = 0 then
for beeploop = 1 to 6
low beepSup
LOW beep
Pause 50
High beep
Pause 100
next beepLoop
beepkill = 1
endif
endif
endif


IF alrt = 0 then
if suprsLEDs = 0 then
LOW led1
HIGH led2
pause 70
LOW led2
HIGH led3
pause 70
LOW led3
else
LOW led2
LOW led3
endif
else
LOW led2
LOW led3
endif

goto mainloop:

'-------------------------------------------------------------------------------
pulseWidthModulator:

ADCIN 6, atod


IF aTOd > 93 AND aTOd <= 186 THEN
DutyCycle1 = 10
ENDIF
IF aTOd > 186 AND aTOd <= 279 THEN
DutyCycle1 = 30
ENDIF
IF aTOd > 279 AND aTOd <= 372 THEN
DutyCycle1 = 50
ENDIF
IF aTOd > 372 AND aTOd <= 465 THEN
DutyCycle1 = 70
ENDIF
IF aTOd > 465 AND aTOd <= 558 THEN
DutyCycle1 = 90
ENDIF
IF aTOd > 558 AND aTOd <= 651 THEN
DutyCycle1 = 110
ENDIF
IF aTOd > 651 AND aTOd <= 744 THEN
DutyCycle1 = 130
ENDIF
IF aTOd > 744 AND aTOd <= 837 THEN
DutyCycle1 = 150
ENDIF
IF aTOd > 837 AND aTOd <= 930 THEN
DutyCycle1 = 170
ENDIF
IF aTOd > 930 AND aTOd <= 1023 THEN
DutyCycle1 = 200
ENDIF

IF aTOd < 45 AND aTOd THEN
DutyCycle1 = 1023
ENDIF

@ HPWM10 1,_DutyCycle1, _Frequency

return
'-------------------------------------------------------------------------------
pwrOnOff:

WHILE onoffbtn = 0
pause 1
onOffBtntst = onOffBtntst + 1
wend
pause 10
serout2 serial,16780,[DEC onOffBtntst, 10]
if onOffBtntst >= 3000 and onOffBtntst <= 65535 then
if suprsLEDs = 0 then
suprsLEDs = 1
else
suprsLEDs = 0
endif
endif

if onOffBtntst >= 100 and onOffBtntst <= 1000 then
toggle onOffRly
if onOffRly = 0 then
suprsLEDs = 0
endif
endif
onOffBtntst = 0
serout2 serial,16780,[DEC suprsLEDs, 10]
goto PowerCheck_Alert:


end

Ryan7777
- 20th December 2010, 18:44
I guess I was thinking that 1000 mS was equal to 1 second and 3000 mS was equal to 3 seconds in PIC time. turns out I was wrong, tweaked my pauses a little and got it to work right.
However, still having serial issues, unimportant now, But I suspect if I were using a better OSC it would clear up. I have a cap across the rails right at the pic but I may tack on a smaller one right across the power pins to see if that helps.

While I'm using up a post I might as well ask another question. I getting ready to do something with serial again, and I want to use a "two's complement addition" error checking routine and I'm a bit afraid of the math involved. I guess an example of some code could help, or if someone could explain how to add three bytes with no carries or how to discard the overflow bits? To explain it in terms of (A+B+C) ? discard some things = 0 using actual PBP operators would be the most helpful. Or if someone has a ready to use routine? or is there something easier?


Thanks as always ahead of time.

cncmachineguy
- 20th December 2010, 19:12
I don't know about your current question, but I think I can shead some light on you solution. You have OSC = 8 for an 8meg clock, but the pic you are using defaults to 4 meg. To use 8 you need to set up OSCCON reg for 8 meg clock. The DEFINE OSC just tells PBP how fast you INTEND to run, so it is able to calculate the delays for your pause. I am guessing your pauses were taking twice as long? so 1000 = 2 sec and 3000 = 6 sec?

This will also affect your serial issues

Dave
- 21st December 2010, 11:59
Ryan7777, I can't help but notice that you are missing a compare value in the last statement:
IF aTOd < 45 AND aTOd ??????? THEN DutyCycle1 = 1023
ENDIF

I think I would write this routine it as follows to save you some cycles:

SELECT CASE aTOd
CASE < 94
DutyCycle1 = 10
CASE < 187
DutyCycle1 = 10
CASE < 280
DutyCycle1 = 30
CASE < 373
DutyCycle1 = 50
CASE < 466
DutyCycle1 = 70
CASE < 559
DutyCycle1 = 90
CASE < 652
DutyCycle1 = 110
CASE < 745
DutyCycle1 = 130
CASE < 838
DutyCycle1 = 150
CASE < 931
DutyCycle1 = 170
CASE <= 1023
DutyCycle1 = 200
END SELECT

That should save you some cpu cycles...

Dave Purola,
N8NTA

Ryan7777
- 21st December 2010, 20:31
Thanks for your replies. I had always assumed that the 16F68Xs just defaulted to 8 instead of 4 Mhz. I'll OSCTUNE it to 8, as you said, it seems like everything is timing out to be twice as long. That explains a lot, Thanks! And yeah, I'll re-write it for select case for the end version, I was still hashing it out and ended up with rough code trying to figure out the timing issue. Now that I have that figured out, and If i can use serout to debug my dimming feature, I can tighten it all up.

Thanks again to the both of you, You guys are awesome.

Ryan

mackrackit
- 21st December 2010, 20:38
i'll osctune it to 8

nope!!!


DEFINE OSC 8
OSCCON = %01110000