febb: (Default)
[personal profile] febb
Намедни тут развлекался программуя свой фонарик с микроконтроллером.
Он питается от NiMH аккумулятора. (Ну потому, что их некуда девать
и они более безопасны и не боятся переразряда и хреновой погоды,
чем литиевые)

Интересный и неожиданный эффект обнаружил. Там есть индуктор
типа ферритоавой катушки для зарядки аккумулятора от USB.
DC-DC buck конвертер для понтов и эффективности.

Так вот работает хорошо, а вот как завинчиваю рядом крепежный болтик, начинает свистеть...
Я подумал, что это пьезоффект керамических конденсаторов.
Но оказалось, что железный болтик идет слишком близко к индуктору
и начинает свистеть, как маленький телефончик.
Не очень громко, но в тишине ночью слышно.
Конечно ничего особенного, этого надо было ожидать,
но все же удивительно. И урок для дизайна таких штук.
По серьезному надо торроид, а лучше закрытый.
Кстати вспомнил, что в советской военной аппаратуре на свалке
видел такие. Люди понимали и знали что делают. Респект!

Под катом программа - просто так, для самых любопытных...

/*
* File:   FlashLight3.c
* Author: 
*
* Created on May 8, 2017, 9:22 PM
*/


// PIC12F510 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config OSC = IntRC      // Oscillator Select (INTOSC with 1.125 ms DRT)
#pragma config WDT = ON         // Watchdog Timer Enable bit (WDT enabled)
#pragma config CP = OFF         // Code Protect (Code protection off)
#pragma config MCLRE = OFF      // Master Clear Enable bit (GP3/MCLR Functions as MCLR)
#pragma config IOSCFS = OFF     // Internal Oscillator Frequency Select bit (4 MHz INTOSC Speed)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include 
//==============================================================================
static const char _copyright[] = "(C) Alex " __DATE__;

#define FUNC   static void
typedef unsigned char byte;
typedef unsigned int uint;

#define ON  1u
#define OFF 0

#define TMR_SEC     31u     // timer counts per second

// ------------------- I/O CONFIGURATION ---------------------------------------
#define BUT_TIMER_BOUNCE        4u      
#define BUT_TIMER_DBLCLICK      30u     
#define BUT_TIMER_IDLE          127u
#define BUT_TIMER_LONG          64u

#define LED_TIMER               16u
#define BAT_TIMER               255u

#define PIN_LED     0b00000001u
#define PIN_POWER   0b00000010u
#define PIN_VBAT    0b00000100u
#define PIN_BUT     0b00001000u
#define PIN_DRIVE   0b00010000u
#define PIN_CHARGE  0b00100000u

#define BIT_LED     GPIObits.GP0
#define BIT_POWER   GPIObits.GP1
#define BIT_VBAT    GPIObits.GP2
#define BIT_BUT     !GPIObits.GP3
#define BIT_DRIVE   GPIObits.GP4
#define BIT_CHARGE  GPIObits.GP5

//============================  ADC  ===========================================

#define ADC_WAIT    while(ADCON0 & 2u);

#define ADC_OFF     ADCON0 = 0b00101100u;
#define ADC_VREF    ADCON0 = 0b01101111u;
#define ADC_VBAT    ADCON0 = 0b01101011u;
#define ADC_POWER   ADCON0 = 0b11100111u;


#define CMP_OFF         0b01010001u
#define CMP_BEAM_BIT    0b10000000u
//---------------------------- timer functions ---------------------------------
#define SYS_TIMER   TMR0

typedef unsigned char timer_t;
typedef unsigned char sys_timer_t;

static timer_t but_timer_bounce, but_timer_dblclick, idle_timer, Timer1, Timer2, led_timer,
        but_timer_long;

FUNC reset_timers()
{
    Timer1 = 0;
    Timer2 = 0;
    but_timer_bounce = 0; 
    but_timer_dblclick = 0;
    led_timer = 0;
    SYS_TIMER = 0;
    idle_timer = 0;
    but_timer_long = 0;
}

#define UPDATE_TIMER(val)   if(val) --val;

FUNC UpdateTimers()
{
	static sys_timer_t timer;

    timer_t t = SYS_TIMER;
	if (t < timer) // roll over
    {
        // Update all timers:
        UPDATE_TIMER(but_timer_bounce)
        UPDATE_TIMER(but_timer_dblclick)
        UPDATE_TIMER(but_timer_long)
		UPDATE_TIMER(Timer1)
		UPDATE_TIMER(Timer2)
		UPDATE_TIMER(led_timer)
        UPDATE_TIMER(idle_timer)
    }
	timer = t;
}

//void timer_delay(timer_t del)
//{
//	timer_t t = Timer;
//	while (Timer - t < del)
//		UpdateTimer();
//}

// ------------------------------ ADC ------------------------------------------

enum StateEnum
{
	STATE_NORMAL,
	STATE_CHARGE,
};

static byte State = STATE_NORMAL;

static byte CheckState()
{
    ADC_POWER
    ADC_WAIT
    ADC_POWER
    ADC_WAIT
	if (ADRES > 240u)   // 
    {
        ADC_VREF
        return STATE_CHARGE;
    }
    ADC_VREF
    return STATE_NORMAL;
}

enum BatteryEnums
{
	BAT_LOW,
	BAT_NORMAL,
	BAT_CHARGE,
	BAT_FULL,
	BAT_MAX
}; 

byte CheckBattery()
{
//    return BAT_CHARGE; //debug
    ADC_VREF
    ADC_WAIT
    ADC_VREF
    ADC_WAIT

	byte vref = ADRES;
    ADC_VBAT
    byte v = (vref << 1) - (vref >> 2); // 1.05V
    ADC_WAIT

    ADC_VBAT
    ADC_WAIT

    if (ADRES < v)
		return BAT_LOW;
    v += vref >> 1;   // 1.35V
	if (ADRES <= v)
		return BAT_NORMAL;
	v += (vref >> 2); //1.5V 
	if (ADRES < v)
		return BAT_CHARGE;
	return BAT_FULL;
}

//-----------------------------------------------------------------------

enum ButtonEnums
{
	BUT_OFF,
	BUT_ON,
	BUT_CLICK,
    BUT_CLICK_LONG,
	BUT_DBLCLICK
};

static byte Button = BUT_OFF;

void CheckButton()
{
	switch (Button)
	{
	case BUT_OFF:
        if(BIT_BUT)
        {
            Button = BUT_ON;
            but_timer_bounce = BUT_TIMER_BOUNCE;
            but_timer_long = BUT_TIMER_LONG;
        }
        break;
        
	case BUT_ON:
		if (BIT_BUT)
            break;
        if (but_timer_dblclick)
        {
            Button = BUT_DBLCLICK;
            but_timer_dblclick = 0;
        }
        else
        {
            if(but_timer_bounce)
            {
                Button = BUT_OFF;
                but_timer_bounce = 0;
            }
            else
            {
                if(but_timer_long)
                {
                    Button = BUT_CLICK;
                    but_timer_dblclick = BUT_TIMER_DBLCLICK; 
                    but_timer_long = 0;
                }
                else
                {
                    Button = BUT_CLICK_LONG;
                    but_timer_dblclick = 0; 
                }
            }
        }
		break;

	default:
		if (BIT_BUT)
            Button = BUT_ON;
        else
            Button = BUT_OFF;

	}//switch (ButtonState)
}//void CheckButton()

static bit bitLight, bitLightSet, bitBeam, bitCharge, bitChargeSet, bitChargeLow,
    bitNightMode;

//------------------------------------- LOOPS ----------------------------------'

#define RUN_LOOPS(loop) \
{                       \
    loop;               \
    loop;               \
    loop;               \
    loop;               \
    loop;               \
    loop;               \
}

FUNC DEL()
{
}

FUNC RunIdle()
{
    BIT_DRIVE = ON;
    NOP();
    BIT_CHARGE = OFF;
    NOP();
	BIT_CHARGE = ON;
	BIT_DRIVE = OFF;
}//static void IdleLoop()

FUNC RunLight()
{
    BIT_DRIVE = ON;
    if(bitBeam)
    {
        DEL();
        DEL();
        DEL();
        DEL();
        DEL();
    	BIT_DRIVE = OFF;
        NOP();
        NOP();
    }
    else
    {
        DEL();
        NOP();
        NOP();
    	BIT_DRIVE = OFF;
        NOP();
        NOP();
    }
}

FUNC RunCharge()
{
    BIT_CHARGE = OFF;
    NOP();
    NOP();
    if(!bitChargeLow)
    {
        DEL();
    }
	BIT_CHARGE = ON;
	DEL();
}

FUNC RunChargeLight()
{
    BIT_CHARGE = OFF;
    BIT_DRIVE = ON;
    if(bitChargeLow)
    {
        if(bitBeam)
        {
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
            NOP();
            BIT_CHARGE = ON;
            NOP();
            NOP();
            NOP();
            NOP();
        }
        else
           BIT_CHARGE = ON;
    	BIT_DRIVE = OFF;
    }
    else
    {
        if(bitBeam)
        {
            DEL();
            NOP();
            NOP();
            BIT_CHARGE = ON;
            NOP();
        	BIT_DRIVE = OFF;
            NOP();
        }            
        else
        {    
            NOP();
        	BIT_DRIVE = OFF;
            NOP();
            NOP();
            BIT_CHARGE = ON;
        }
    }
}

//00000000000000000000000000000000000000000000000000000000000000000000000000000

FUNC InitMCU()
{
	OPTION	= 0b01000110;   // 64 timer prescale, no pullups
	TRIS	= PIN_VBAT | PIN_BUT | PIN_POWER;
	GPIO	= PIN_CHARGE;
	ADC_POWER
    CM1CON0 = CMP_OFF;
}//static void InitMCU()


FUNC Sleep()
{
    ADC_OFF
    GPIO;
    SLEEP();
}

//========================== MAIN =============================================

void main()
{
    InitMCU();
    byte oldState = STATE_NORMAL; 
	for (;;) // ----- MAIN LOOP -------
	{
		CLRWDT();
		State = CheckState();
        if(State != oldState)
        {
            BIT_LED = OFF;
            bitCharge = OFF;
            bitLight = OFF;
            bitLightSet = bitLight;
            bitNightMode = OFF;
            reset_timers();
            if(State == STATE_CHARGE)
            {
                bitChargeSet = bitCharge = ON;
                bitChargeLow = ON;
                led_timer = LED_TIMER;
                Timer1 = 0;
                Timer2 = BAT_TIMER;
                BIT_LED = ON;
            }
            oldState = State;
        }
        UpdateTimers();
        CheckButton();
        switch(Button)
        {
        case BUT_OFF:
            break;
        case BUT_ON:
            idle_timer = BUT_TIMER_IDLE;
            break;
        case BUT_CLICK:
            if(bitLight)
                bitBeam = !bitBeam;
            if(bitNightMode)
            {
                bitNightMode = OFF;
                idle_timer = 0;
            }
            break;
        case BUT_DBLCLICK:
            bitLight = !bitLight;
            bitLightSet = bitLight;
            if(bitLight)
                bitBeam = ON;
            else
                idle_timer = 0;
            break;
        case BUT_CLICK_LONG:
            bitNightMode = ON;
            bitLight = OFF;
            idle_timer = 0;
            break;                    
        }//switch(Button)

        switch(State)
        {
        case STATE_NORMAL:
            if(bitLight)
                RUN_LOOPS(RunLight())
            else
            {
                RunIdle();
                if(bitNightMode)
                    RunIdle();
                else
                    if(idle_timer == 0)
                    {
                        RunIdle();
                        Sleep();
                    }                    
            }
            break;
        case STATE_CHARGE:
            if(led_timer == 0)
            {
                led_timer = LED_TIMER;
                if(BIT_LED)
                {
                    if(bitCharge)  
                        BIT_LED = OFF;
                    if(Timer2 == 0)
                    {
                        bitCharge = OFF;
                        bitLight = OFF;
                        BIT_LED = OFF;
                    }
                }
                else
                {
                    if(Timer2 == 0 && bitCharge == 0)
                    {
                        Timer2 = BAT_TIMER;
                        byte bat = CheckBattery();
                        if(bitChargeSet)
                            bitCharge = bat != BAT_FULL;
                        else
                            bitCharge = bat == BAT_LOW || bat == BAT_NORMAL;
                        bitChargeSet = bitCharge;
                        bitLight = bitLightSet;
                        bitChargeLow = bat == BAT_LOW;
                    }
                    BIT_LED = ON;
                }
            }//if(led_timer == 0)
            CLRWDT();
            if(bitLight)
                if(bitCharge)
                    RUN_LOOPS(RunChargeLight())
                else
                    RUN_LOOPS(RunLight())
            else
                if(bitCharge)
                    RUN_LOOPS(RunCharge())
            if(Timer1 == 0)
            {
                RunIdle();
                RunIdle();
                RunIdle();
                Timer1 = 1u;
            }
            if(idle_timer)
                RunIdle();
            if(bitNightMode)
            {
                RunIdle();
                RunIdle();
            }
            break;       
        }//switch(State)
        // ------ CHARGE STATE --------
	}//for(;;) // MAIN LOOP
}//void main(void) 



Profile

febb: (Default)
febb

March 2022

S M T W T F S
  1 2 345
6 7 89 101112
13141516171819
20212223242526
2728293031  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Mar. 10th, 2026 08:05 am
Powered by Dreamwidth Studios