Mike - K8LH
Well-Known Member
I was surprised that the logic is subtly complex and I was wondering how someone else might tackle the problem?
In my example (below) I'm using XC8 and coding for a 14-pin 16F1503. I connected active low <left>, <right>, and <brake> switches to RA0, RA1, and RA2, respectively, and I connected active high left and right turn signal LEDs to RA4 and RA5, respectively.
I'm using a simple timed loop running at a 25-millisecond switch "debounce" interval and I derive a non-blocking "flash timer" function from within that loop to flash (toggle) an active turn signal LED at a 250-millisecond flash rate interval. I start the "flash timer" function on detecting a turn signal switch "new press" state and I turn off the "flash timer" function on detecting the debounced switch "release" state at the end of the flash rate interval. Turn signal "on" and "off" latency is the 250-millisecond flash rate interval.
The "turns" variable contains either an RA4 (left) or an RA5 (right) turn signal LED bit mask when either turn signal is active and provides a simple mechanism for toggling the active turn signal LED at the end of each 250-millisecond flash rate interval. The brake light logic also relies on the "turns" bit mask variable to determine which LEDs it needs to turn on or off.
I'd love to see some alternative programming methods/algorithms for this application.
Cheerful regards, Mike
In my example (below) I'm using XC8 and coding for a 14-pin 16F1503. I connected active low <left>, <right>, and <brake> switches to RA0, RA1, and RA2, respectively, and I connected active high left and right turn signal LEDs to RA4 and RA5, respectively.
I'm using a simple timed loop running at a 25-millisecond switch "debounce" interval and I derive a non-blocking "flash timer" function from within that loop to flash (toggle) an active turn signal LED at a 250-millisecond flash rate interval. I start the "flash timer" function on detecting a turn signal switch "new press" state and I turn off the "flash timer" function on detecting the debounced switch "release" state at the end of the flash rate interval. Turn signal "on" and "off" latency is the 250-millisecond flash rate interval.
The "turns" variable contains either an RA4 (left) or an RA5 (right) turn signal LED bit mask when either turn signal is active and provides a simple mechanism for toggling the active turn signal LED at the end of each 250-millisecond flash rate interval. The brake light logic also relies on the "turns" bit mask variable to determine which LEDs it needs to turn on or off.
I'd love to see some alternative programming methods/algorithms for this application.
Cheerful regards, Mike
C:
/*****************************************************************
* File: Basic_Turn_Signals.c *
* Author: Mike McLaren, K8LH *
* Date: 15-May-2017 *
* *
* 16F1503 Simple Turn Signal & Brake Light Exercise *
* *
* IDE: MPLAB 8.92 *
* Lang: XC8 v1.35 *
* *
*****************************************************************/
#include <xc.h>
// config 1
#pragma config FOSC = INTOSC //
#pragma config WDTE = OFF //
#pragma config PWRTE = ON //
#pragma config MCLRE = OFF //
#pragma config CP = OFF //
#pragma config BOREN = ON //
#pragma config CLKOUTEN = OFF //
// config 2
#pragma config WRT = OFF //
#pragma config STVREN = ON //
#pragma config BORV = LO //
#pragma config LPBOR = OFF //
#pragma config LVP = OFF //
#define _XTAL_FREQ 500000
/* *
* variables *
* */
unsigned char turns = 0; // active turn signal mask
unsigned char flash = 10; // flash rate timer
unsigned char swnew = 0; // switch state filter
unsigned char swlat = 0; // switch state latch
/*****************************************************************
* main *
* */
void main()
{ //
ANSELA = 0; // adc off, digital I/O
ANSELC = 0; // adc off, digital I/O
TRISA = 0b00000111; // RA2(brake) RA1(right) RA0(left)
WPUA = 0b00000111; // weak pull-ups on RA2..RA0
OPTION_REG &= 0b01111111; // global weak pull-up enable
OSCCON = 0b01010000; // intosc = 500kHZ
while(1) //
{ __delay_ms(25); // 25-ms debounce/loop interval
/* *
* K8LH Parallel Switch State Logic (and "new press" filter) *
* *
* swnew ___---___---_____ invert active lo switches *
* swlat ____---___---____ switch state latch *
* swnew ___-__-__-__-____ changes, press or release *
* swnew ___-_____-_______ filter out 'release' bits *
* */
swnew = ~PORTA; // invert active lo switches
swnew &= 7; // on the RA2..RA0 pins only
swnew ^= swlat; // changes, press or release
swlat ^= swnew; // update switch state latch
swnew &= swlat; // filter out 'release' bits
/* *
* check for Right or Left turn signal "new press" state *
* */
if(swnew & 1) // if Left Sw (RA0) "new press"
turns = 0b00010000; // active Lt signal (RA4 mask)
if(swnew & 2) // if Right Sw (RA1) "new press"
turns = 0b00100000; // active Rt signal (RA5 mask)
/* *
* toggle active turn signal LED at the flash rate interval *
* */
if(turns) // if either signal active
{ if(--flash == 0) // if flash rate interval
{ flash = 10; // reset flash timer (250-msecs)
if(swlat & 3) // if switch still "pressed"
LATA ^= turns; // toggle turn signal LED
else // turn signal switch "released"
turns = 0; // turn off turn signal
} //
} //
/* *
* brake logic (applied during each 25-msec loop interval) *
* *
* brake switch on & neither turn signal -> light both LEDs *
* brake switch on & active left signal -> light right LED *
* brake switch on & active right signal -> light left LED *
* brake switch off -> only active turn signal LED lighted *
* */
if(swlat & 4) // if Brake Sw (RA2) "pressed"
LATA |= (0b00110000 ^ turns);
else
LATA = ((LATA & 0b11001111) | (LATA & turns));
} // end while(1)
} // end main()
Last edited: