如果機車的方向燈泡是傳統的燈絲燈泡,那改 LED 後,閃光器多半會不正常。

我的 KTR 就是這樣,換上 LED 方向燈,它只會亮著,一閃都不閃。

最好解決的方式是到網拍去買一個 LED 用的閃光器換上,一個 100 以內搞定。

但是這個東西那麼簡單,所以就自己搞一個來玩玩囉.......

先畫電路圖:

001  

主控 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;
}

創作者介紹
創作者 箱子裡的貓 的頭像
Bill Suen

箱子裡的貓

Bill Suen 發表在 痞客邦 留言(0) 人氣( 975 )