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) 



This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

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 05:50 am
Powered by Dreamwidth Studios