如果機車的方向燈泡是傳統的燈絲燈泡,那改 LED 後,閃光器多半會不正常。
我的 KTR 就是這樣,換上 LED 方向燈,它只會亮著,一閃都不閃。
最好解決的方式是到網拍去買一個 LED 用的閃光器換上,一個 100 以內搞定。
但是這個東西那麼簡單,所以就自己搞一個來玩玩囉.......
先畫電路圖:
主控 IC 是 PIC12F615,機車電源是 12V,所以使用 LM1117-5.0 降壓成 5V 給控制電路用。
10K 的可變電阻是用來調整閃光的速度,N-MOSFET 2N7002 用來隔離 12V 及 5V 的電源,
控制用的 P-MOSFET PA502 最大可以控制到 3A,這樣應該夠用了。
下面是程式:
1. config12F615.h
設定 IC 及參、變數,宣告使用的函數
#ifndef __CONFIG12F615_H
#define __CONFIG12F615_H
//define configurationbits.
#if defined (__DEBUG)
__CONFIG (FOSC_INTOSCIO&WDTE_OFF&PWRTE_OFF&MCLRE_ON&CP_OFF&IOSCFS_4MHZ&BOREN_OFF);
#else
__CONFIG (FOSC_INTOSCIO&WDTE_OFF&PWRTE_ON&MCLRE_ON&CP_ON&IOSCFS_4MHZ&BOREN_ON);
#endif
//define MCU frequency.
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
//change variable type define.
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long uint32_t;
typedef char int8_t;
typedef int int16_t;
typedef long int32_t;
#define ADJ 2
#define OUTPUT GP4
#define ON 1
#define OFF 0
#define SAMPLE_RATE 8
void interrupt isr(void);
void systemInit(void);
void A2D(uint8_t);
uint8_t LEDflash(uint16_t, uint16_t);
volatile uint16_t cnt = 0;
volatile uint16_t tmpADvalue = 0;
volatile uint16_t avgADvalue = 0;
volatile uint16_t outputValue = 100;
volatile uint8_t ADcnt;
typedef union
{
uint16_t intValue;
struct
{
uint8_t LSB;
uint8_t MSB;
}intByte;
}intFormat;
intFormat ADresult;
#define AD_value ADresult.intValue
#define AD_LSB ADresult.intByte.LSB
#define AD_MSB ADresult.intByte.MSB
struct
{
uint8_t A2D_flag :1;
uint8_t sampleFinishFlag :1;
uint8_t readFlag :1;
uint8_t :5;
}controlFlag;
#define A2D_flag controlFlag.A2D_flag
#define sampleFinishFlag controlFlag.sampleFinishFlag
#define readFlag controlFlag.readFlag
#endif
2. main.c 這是使用狀態機的寫法:
#include <pic.h>
#include "config_12F615.h"
void main()
{
systemInit();
while (1)
{
if(A2D_flag) //每 1 mSec 取樣一次.(其實 10 msec 取一次就足夠了)
{
A2D_flag = 0;
A2D(ADJ);
tmpADvalue += AD_value;
ADcnt++;
}
if(ADcnt >= SAMPLE_RATE) //取平均值
{
ADcnt = 0;
avgADvalue = tmpADvalue / SAMPLE_RATE;
tmpADvalue = 0;
sampleFinishFlag = 1;
}
if(!readFlag && sampleFinishFlag) //只在 PWM 一個週期完成後才讀一次數值
{
outputValue = avgADvalue;
readFlag = 1;
sampleFinishFlag = 0;
cnt = 0;
}
OUTPUT = LEDflash(outputValue*2,outputValue); //軟體模擬的 PWM 輸出
}
}
void interrupt isr(void)
{
if(T0IF)
{
T0IF = 0;
cnt++; //increase every 1 msec.
TMR0 += 131;
A2D_flag = 1;
}
}
void systemInit(void)
{
ANSEL = 0x34; //set frequence = Frc, enable AN2.
GPIO = 0;
WPU = 0;
TRISIO = 0b00001100; //GP2 is input. Defult GP3 allways input.
OPTION_REG = 0b11000010; //TMR0 source set to internal RC, assign prescale to TMR0 (1:8).
ADCON0 = 0x81; //set right justify format, A/D ON.
TMR0 += 100;
T0IE = 1;
GIE = 1;
}
void A2D(uint8_t channel)
{
uint8_t temp; // Temp storage
AD_value = 0;
temp = channel << 2; // Shift channel value 2 bits left
ADCON0 &= 0x81; // clear old chennal value.
ADCON0 |= temp; // Logically OR shifted channel value into place in ADCON0
GO_nDONE = 1; // Initiate conversion on selected channel
NOP( );
while (GO_nDONE); // Poll ADGO bit until it clears, indicating conv. done
AD_MSB = ADRESH;
AD_LSB = ADRESL;
}
uint8_t LEDflash(uint16_t period,uint16_t duty)
{
if(cnt >= period)
readFlag = 0;
if(cnt < duty)
return ON;
else //if((cnt >= duty)) && (cnt < period))
return OFF;
}
請先 登入 以發表留言。