skeeterb
Member
I've been working on this for a while with the help of 3v0 in the chat room, and have gotten this code working. Using a potentiometer or preset you can adjust the timing of this code from 1 second to 60 seconds. The Red/Green timing is calculated using the formula 1+((rslt+1)/17) to determine the timing for the Red to Green change and the Green to Amber is half of the value of the Red to Green variable.
here is the code and the images generated by FlowCode.
here is the code and the images generated by FlowCode.
Code:
//************************************************************************************
//**
//** File name: C:\temp\Traffic Light.c
//** Generated by: Flowcode v4.0.0.53
//** Date: Monday, June 29, 2009 17:18:35
//** Licence: Demo
//**
//** ***DEMO VERSION***
//**
//**
//** NOT FOR COMMERCIAL USE
//**
//** http://www.matrixmultimedia.com
//************************************************************************************
#define MX_PIC
//Defines for microcontroller
#define P16F690
#define MX_EE
#define MX_EE_SIZE 256
#define MX_SPI
#define MX_SPI_BCB
#define MX_SPI_SDI 4
#define MX_SPI_SDO 7
#define MX_SPI_SCK 6
#define MX_UART
#define MX_UART_B
#define MX_UART_TX 7
#define MX_UART_RX 5
#define MX_I2C
#define MX_MI2C
#define MX_I2C_B
#define MX_I2C_SDA 4
#define MX_I2C_SCL 6
#define MX_PWM
#define MX_PWM_CNT 1
#define MX_PWM_TRIS1 trisc
#define MX_PWM_1 5
//Functions
#include <system.h>
#pragma CLOCK_FREQ 4000000
//Configuration data
#pragma DATA 0x2007, 0x30c4
//Internal functions
#include "C:\Flowcode V4\FCD\internals.h"
//Macro function declarations
void FCM_Operation();
//Variable declarations
short FCV_REDGREEN;
char FCV_FLASHER;
short FCV_AMBERRED;
short FCV_RSLT;
//Defines:
/**** Macro Substitutions ****
1 = Which ADC Channel
40 = Acquisition time
3 = Conversion Speed
0 = VRef+ Option
500 = VRef Voltage x 0.01V
******************************/
//ADC0: //Macro function declarations
void FCD_ADC0_SampleADC();
char FCD_ADC0_ReadAsByte();
short FCD_ADC0_ReadAsInt();
float FCD_ADC0_ReadAsVoltage();
void FCD_ADC0_ReadAsString(char* FCR_RETVAL, char FCR_RETVAL_SIZE, char NumBytes);
//ADC0: //Macro implementations
void FCD_ADC0_SampleADC()
{
/*******Supported Devices******************************************************************
// 16F616, 16F676, 16F677, 16F684, 16F685, 16F687, 16F688, 16F689, 16F690
******************************************************************************************/
#define MX_ADC_CHANNEL 1
#define MX_ADC_SAMP_TIME 40
#define MX_ADC_CONV_SP 3
#define MX_ADC_VREF_OPT 0
//set up ADC conversion
char old_tris, cnt;
//assign conversion rate
adcon1 = ((MX_ADC_CONV_SP & 0x07) << 4);
//find appropriate bit
#if (MX_ADC_CHANNEL == 0)
#define MX_ADC_TRIS_REG trisa
#define MX_ADC_TRIS_MSK 0x01
ansel = 0x01;
#endif
#if (MX_ADC_CHANNEL == 1)
#define MX_ADC_TRIS_REG trisa
#define MX_ADC_TRIS_MSK 0x02
ansel = 0x02;
#if (MX_ADC_VREF_OPT == 1)
#pragma error "Target device is currently using AN1 for VREF+"
#endif
#endif
#if (MX_ADC_CHANNEL == 2)
#define MX_ADC_TRIS_REG trisa
#define MX_ADC_TRIS_MSK 0x04
ansel = 0x04;
#endif
#if (MX_ADC_CHANNEL == 3)
#define MX_ADC_TRIS_REG trisa
#define MX_ADC_TRIS_MSK 0x10
ansel = 0x08;
#endif
#if (MX_ADC_CHANNEL == 4)
#define MX_ADC_TRIS_REG trisc
#define MX_ADC_TRIS_MSK 0x01
ansel = 0x10;
#endif
#if (MX_ADC_CHANNEL == 5)
#define MX_ADC_TRIS_REG trisc
#define MX_ADC_TRIS_MSK 0x02
ansel = 0x20;
#endif
#if (MX_ADC_CHANNEL == 6)
#define MX_ADC_TRIS_REG trisc
#define MX_ADC_TRIS_MSK 0x04
ansel = 0x40;
#endif
#if (MX_ADC_CHANNEL == 7)
#define MX_ADC_TRIS_REG trisc
#define MX_ADC_TRIS_MSK 0x08
ansel = 0x80;
#endif
#if (MX_ADC_CHANNEL == 8)
#define MX_ADC_TRIS_REG trisc
#define MX_ADC_TRIS_MSK 0x40
anselh = 0x01;
#endif
#if (MX_ADC_CHANNEL == 9)
#define MX_ADC_TRIS_REG trisc
#define MX_ADC_TRIS_MSK 0x80
anselh = 0x02;
#endif
#if (MX_ADC_CHANNEL == 10)
#define MX_ADC_TRIS_REG trisb
#define MX_ADC_TRIS_MSK 0x10
anselh = 0x04;
#endif
#if (MX_ADC_CHANNEL == 11)
#define MX_ADC_TRIS_REG trisb
#define MX_ADC_TRIS_MSK 0x20
anselh = 0x08;
#endif
//sanity check
#ifndef MX_ADC_TRIS_REG
#pragma error "ADC Type 3 conversion code error - please contact technical support"
#endif
//store old tris value, and set the i/o pin as an input
old_tris = MX_ADC_TRIS_REG;
MX_ADC_TRIS_REG = MX_ADC_TRIS_REG | MX_ADC_TRIS_MSK;
//turn ADC on
adcon0 = 0x01 | (MX_ADC_CHANNEL << 2);
//assign VREF functionality
#if (MX_ADC_VREF_OPT == 1)
set_bit(adcon0, VCFG);
#endif
//wait the acquisition time
cnt = 0;
while (cnt < MX_ADC_SAMP_TIME) cnt++;
//begin conversion and wait until it has finished
adcon0 = adcon0 | 0x02;
while (adcon0 & 0x02);
//restore old tris value, and reset adc registers
MX_ADC_TRIS_REG = old_tris;
ansel = 0x00;
adcon0 = 0x00;
#if(anselh)
anselh = 0x00;
#endif
#undef MX_ADC_TRIS_REG
#undef MX_ADC_TRIS_MSK
#undef MX_ADC_SAMP_TIME
#undef MX_ADC_CHANNEL
#undef MX_ADC_CONV_SP
#undef MX_ADC_VREF_OPT
}
char FCD_ADC0_ReadAsByte()
{
FCD_ADC0_SampleADC();
return adresh;
}
short FCD_ADC0_ReadAsInt()
{
short iRetVal;
FCD_ADC0_SampleADC();
iRetVal = (adresh << 2);
iRetVal = iRetVal | (adresl >> 6);
return (iRetVal);
}
float FCD_ADC0_ReadAsVoltage()
{
int iSample;
float fSample, fVoltage, fVperDiv;
#define MX_ADC_VREF_V 500
iSample = FCD_ADC0_ReadAsInt(); //Read as 10-bit Integer
fVoltage = float32_from_int32(MX_ADC_VREF_V); //Convert reference voltage count to floating point (0 - 500 x 10mV)
fVoltage = float32_mul(fVoltage, 0.01); //Convert reference voltage count to actual voltage (0 - 5)
fVperDiv = float32_mul(fVoltage, 0.000976); //Convert actual voltage to voltage per division (VRef / 1024)
fSample = float32_from_int32(iSample); //Convert to floating point variable
fVoltage = float32_mul(fSample, fVperDiv); //Calculate floating point voltage
#undef MX_ADC_VREF_V
return (fVoltage);
}
void FCD_ADC0_ReadAsString(char* FCR_RETVAL, char FCR_RETVAL_SIZE, char NumBytes)
{
float fVoltage;
if (NumBytes > FCR_RETVAL_SIZE)
NumBytes = FCR_RETVAL_SIZE;
fVoltage = FCD_ADC0_ReadAsVoltage();
FCI_FLOAT_TO_STRING(fVoltage, 2, FCR_RETVAL, NumBytes); //Convert to String
}
//Macro implementations
void FCM_Operation()
{
//Main Branch of Traffic Light Operation
//Call Component Macro
//Call Component Macro: rslt=ADC(0)::ReadAsInt
FCV_RSLT = FCD_ADC0_ReadAsInt();
//Timing Calculations
//Calculation:
// RedGreen = 1+((rslt+1)/17)
// AmberRed = RedGreen/2
FCV_REDGREEN = 1+((FCV_RSLT+1)/17);
FCV_AMBERRED = FCV_REDGREEN/2;
//Delay
//Delay: 30 ms
delay_ms(30);
//N/S Red E/W Green
//Output: 0x21 -> PORT C
trisc = 0x00;
portc = 0x21;
//Delay
//Delay: RedGreen s
delay_s(FCV_REDGREEN);
//N/S Red E/W Amber
//Output: 0x11 -> PORT C
trisc = 0x00;
portc = 0x11;
//Delay
//Delay: AmberRed s
delay_s(FCV_AMBERRED);
//N/S Green E/W Red
//Output: 0x0c -> PORT C
trisc = 0x00;
portc = 0x0c;
//Delay
//Delay: RedGreen s
delay_s(FCV_REDGREEN);
//N/S Amber E/W Red
//Output: 0x0A -> PORT C
trisc = 0x00;
portc = 0x0A;
//Delay
//Delay: AmberRed s
delay_s(FCV_AMBERRED);
}
void main()
{
//Initialisation
ansel = 0;
anselh = 0;
//Interrupt initialisation code
option_reg = 0xC0;
//Loop
//Loop: While 1
while (1)
{
//Input
//Input: A0 -> Flasher
trisa = trisa | 0x01;
FCV_FLASHER = ((porta & 0x01) == 0x01);
//Decision
//Decision: Flasher > 0?
if (FCV_FLASHER > 0)
{
//Comment:
//When Flasher switch is high, This subroutine flashes the N/S Amber and
//the E/W Red with a 1 second delay
//Output
//Output: 0x11 -> PORT C
trisc = 0x00;
portc = 0x11;
//Delay
//Delay: 1 s
delay_s(1);
//Output
//Output: 0 -> PORT C
trisc = 0x00;
portc = 0;
//Delay
//Delay: 1 s
delay_s(1);
} else {
//Call Macro
//Call Macro: Operation
FCM_Operation();
}
if ((1) == 0) break;
}
mainendloop: goto mainendloop;
}
void interrupt(void)
{
}