Francois Druilhe
Целью этого проекта является создание автономного почтового ящика, который, отображая номер дома на светящемся табло, питается только энергией солнца. При отсутствии солнца система работает от аккумуляторов.
Окончательный вид после сборки
В ночное время центральная цифра светится с максимальной интенсивностью, а яркость остальных регулируется с помощью ШИМ.
В темноте PIC контроллер управляет свечением трех цифр.
Почтовый ящик питается от солнечной батареи из поликремневых элементов. Номинальное напряжение батареи 5 В, ток 80 мА. Батарея заряжает 3 NiMH аккумулятора типоразмера AA.
Программа контроллера приведена в конце статьи.
Объяснение работы схемы
(Принципиальную схему можно скачать в формате PDF).
Charger_Control:
Солнечная батарея заряжает три NiMH аккумулятора через составной транзистор T5 (2N2907) и T4 (2N1711). Составной транзистор имеет очень маленький обратный ток, что важно, когда солнца нет, а аккумуляторы полностью заряжены. Зарядом управляет контроллер, подавая уровень «1» через диод D5 и транзистор T6 на составной транзистор. Для защиты аккумуляторов от перезаряда и продления их срока службы, в схему добавлен стабилитрон DZ6 с напряжением стабилизации 4.6 В. Эта функция не поддерживается программой контроллера и рассчитана на будущее развитие схемы.
LED_OR_control:
Три цифры, каждая из которых состоит примерно из 20 белых светодиодов, управляются отдельно тремя транзисторами 2N1711. Управляющий сигнал каждого транзистора представляет собой логическое «ИЛИ» из ШИМ сигнала постоянной фоновой засветки и «мигающей компоненты», генерируемой контроллером.
Sun_Sense:
Это просто напряжение с выхода фильтра нижних частот, состоящего из R8 и C6. Имейте ввиду, что ток утечки PIC может влиять на это напряжение. Поэтому R8 не должно превышать 39 кОм.
Vbat_sense:
На двух включенных последовательно диодах падает примерно 1.3 В. Это напряжение используется в качестве опорного, с которым котроллер сравнивает напряжение на аккумуляторах. Эта функция не поддерживается программой контроллера и рассчитана на будущее развитие схемы.
Cpu:
Тактовая частота контроллера задается кварцевым резонатором 32.768 кГц. Низкая частота выбрана для того, чтобы уменьшить ток потребления. На такой частоте PIC16F628 способен работать при напряжении до 3 В.
Внутренние соединения
Печатная плата вблизи
Поведение устройства
При разряженном аккумуляторе контроллер выполняет бесконечный цикл с периодом порядка 1 с, включая в каждом проходе цикла красный светодиод.
В дневное время сигнал SunSense имеет высокий уровень, и контроллер не выполняет никаких действий (кроме периодического «мигания»). Зеленый светодиод включен. При не полностью заряженных аккумуляторах, солнечная батарея подзаряжает их. Если напряжение на аккумуляторах превысит 4.6 В, стабилитрон DZ6 начнет пропускать ток на землю, защищая аккумуляторы от перезаряда. В будущем предполагается использовать сигналы Vbat_sense и Stop_Charge.
В ночное время уровень сигнала SunSense становится низким, и контроллер приступает к выполнению следующих действий:
- Генерации ШИМ с частотой 100 Гц и коэффициентом заполнения 5%
- Генерации сигналов «мигания» по трем отдельным каналам с периодом 1 мин.
Исходный код программы
// --------------------------------------------------------------------------------------
//
// Boite aux Lettres
//
// (C) F. Druilhe 30 Juillet 2009
//
// --------------------------------------------------------------------------------------
#include
// Define Crystal Oscilator frequency
#define _XTAL_FREQ 32768UL
// Configure the Chip
__CONFIG(LP & WDTDIS & PWRTDIS & BORDIS & LVPEN & UNPROTECT);
// ------------------- Global Variables -----------------------
#define LED_SEQ 60
unsigned char led_count; // Led Counter
unsigned char program; // Number of sequence to execute
unsigned char sec_count; // Second counter
unsigned char min_count; // Minute counter
unsigned char hour_count; // Hours counter
unsigned int day_count; // Day counter
unsigned char sun_rise; // First sun variation
// ----- Local Working variables
char c, d; // Local Variables
// Led Sequence
char led_table[LED_SEQ] = {/* "8", "O", "1", void */
0b0000, 0b0010, 0b1010, 0b1000, 0b1000, 0b1100, 0b0100, 0b0000, 0b0000, 0b0000,
0b0000, 0b0010, 0b1010, 0b1000, 0b1000, 0b1100, 0b0100, 0b0000, 0b0000, 0b0000,
0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000,
0b1110, 0b1110, 0b1000, 0b1000, 0b0110, 0b0110, 0b1110, 0b1110, 0b0000, 0b0000,
0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000,
0b0010, 0b1000, 0b0100, 0b0000, 0b0100, 0b1000, 0b0010, 0b0000, 0b0000, 0b0000
};
// Initializations
void initPORT(void)
{
// Port A: RA0: Vref_in
// RA1: L3Ctrl_out
// RA2: L1Ctrl_out
// RA3: L2Ctrl_out
// RA4: nc
// RA5: MCLR input
// RA6: Osc
// RA7: Osc
TRISA = 0b11110001;
// Port B: RB0: CellSence_in
// RB1: Rx_in
// RB2: Tx_out
// RB3: PWM_out
// RB4: Conf0_in
// RB5: Conf1_in
// RB6: StopChrg_out
// RB7: GLedCtrl_out
// port directions: 1=input, 0=output
TRISB = 0b00110011;
// Option: PS: 000
// PSA: 0 assigned to Timer0
// T0SE: 0 faling edge
// T0CS: 0 internal clock
// INTEDG: 1 rising Edge (sunshine)
// nRBPU: 1 pull-ups disable
OPTION = 0b11000000;
// Set the Port to off
PORTB = 0b00000000;
PORTA = 0b00000000;
// Program PWM frequency is 100Hz with a ratio is 5%, active high
// PR2: 0x51 (81); Freq = 32768/4/(PR2+1) = 99.9024 Hz
PR2 = 0x51;
// CCPR1L: 0x8 (16/4); FreqOn = 32768/(PR2+1) = 2000Hz
CCPR1L = 0x4;
// CCP1CON: CCP1X: 0 Lsb
// CCP1Y: 0 ..
// CCP1M3..0: 1110 PWM active high
CCP1CON = 0x0E;
// T2CON: T2CKPS1..0: 00 Predividor by 1
// TMR2ON: 0 Off
// TOUTPS3..0: 0000 Postdividor by 1
T2CON = 0;
}
#define enable_PWM T2CON = 0b00000100
#define disable_PWM T2CON = 0b00000000
void initVAR()
{
// Init Variables
program = 0;
led_count = 0;
sun_rise = 0;
// Init Time
sec_count = 0;
min_count = 0;
hour_count = 0
day_count = 0;
}
// Main
void main(void)
{
initPORT(); // Init platform Ports
initVAR(); // Init Variables
while (1){
PORTB = 0b10000000; // Set Green Led on
__delay_ms(100); // small delay
PORTB = 0b00000000; // Clear Green Led off
//------- Read Sun Level
c = PORTB & 0b00000001;
if (c) {
//----------- Sun raise: reset everything
led_count = 0; // Reset Led Counter
sun_rise = 0;
PORTA = 0b00000000; // Clear all Led Bits
disable_PWM;
} else {
//----------- Sun fall: light on Leds
if (!sun_rise) {
enable_PWM;
sun_rise = 1;
}
// Execute the current led sequence
c = led_table[led_count] & 0b00001110; // Get the sequence in the table
// and mask in case
PORTA = c; // Set leds
led_count++; // Increment the Led Counter
if (led_count >= LED_SEQ) led_count = 0; // Reset led sequence
}
//---------------- Complement to 1 second --------------------
__delay_ms(900); // one second
//------- Increment overall time
sec_count++;
if (sec_count >= 60) {
sec_count = 0x0;
min_count++;
if (min_count >= 60) {
min_count = 0x0; // Hours not manged yet
hour_count++;
if (hour_count >= 24) {
hour_count = 0;
day_count++; // Increment Day
}
}
}
}
}