Поломал UNO
- Войдите на сайт для отправки комментариев
Чт, 09/01/2014 - 12:14
Есть работающий код:
// Для работы с сим-картой.
#include "SIM900.h"
// Для работы с датчиком температуры и влажности.
#include <dht.h>
// Для хранения переменных во флеш памяти.
#include <avr/pgmspace.h>
// Сериал порт.
#include <SoftwareSerial.h>
// Количество замеров, которые могут храниться в памяти.
//const int samplesCount = 10;
// Массив семплов, которые не отправлены.
//int samples[samplesCount];
// Номер последнего обновленного семпла в массиве.
//int lastSamplePointer = 0;
// Обьект датчика температуры, влажности.
dht DHT;
// Пин для датчика температуры и влажности.
#define dht_dpin A0
// Текущие значения с датчика.
float currentHumidity = 0;
float currentTemperature = 0;
unsigned int minutes = 0;
// Задаёт интервал сна устройства, в минутах.
unsigned char SendIntervalInMinutes = 5;
// Активация отправки.
unsigned char needSend;
volatile unsigned char WDT_wake;
volatile unsigned char SleepTimeInSec = 60;
// Обработчик прерываний по срабатыванию охранного таймера.
ISR( WDT_vect ) {
// Увеличит счетчик прерываний.
static unsigned char WDT_counter;
// Отсчет минут.
if ( WDT_counter++ == SleepTimeInSec ) {
WDT_counter = 0;
if ( minutes++ == SendIntervalInMinutes ) {
minutes = 0;
// Флаг о необходимости выполнения задачи отправки данных.
needSend = 1;
}
}
asm ( "WDR" );
}
void setup_WDT( void ) {
asm ( "CLI" );
asm ( "WDR" );
// Сброс флага срабатывания.
MCUSR &= ~( 1 << WDRF );
WDTCSR = ( 1 << WDCE ) | (1 << WDE );
// Настройка сторожевого таймера на период в 1 сек.
// Перевод в режим работы генерирования прерываний.
WDTCSR = ( 1 << WDP2 ) | ( 1 << WDP1 ) | ( 1 << WDIE ) | ( 1 << WDIF );
asm ( "SEI" );
}
void off_WDT( void ) {
asm ( "CLI" );
asm ( "WDR" );
// Сброс флага срабатывания.
MCUSR &= ~( 1 << WDRF );
WDTCSR = ( 1 << WDCE ) | ( 1 << WDE ) | ( 1 << WDIF );
// Turn off WDT.
WDTCSR = 0x00;
asm ( "SEI" );
}
void sys_sleep( void ) {
asm ( "CLI" );
// Выключает АЦП.
ADCSRA &= ~( 1 << ADEN );
// Конфигурирует режим power-down.
SMCR = ( 1 << SE ) | ( 1 << SM1 );
asm ( "SEI" );
asm ( "SLEEP" );
}
void sys_wake( void ) {
// Конфигурация режима power-down.
SMCR = 0x00;
}
// Считывание семпла.
void createSample() {
Serial.println( "Creating Sample..." );
DHT.read11( dht_dpin );
currentHumidity = DHT.humidity;
currentTemperature = DHT.temperature;
// Установить дату.
//this->sampleDate = '000000000000';
Serial.println( "Created." );
}
// Процедура передачи данных на сервер.
boolean send() {
//Serial.println( "Testing GSM..." );
// Проверка модема.
//if ( gsm.begin( 2400 ) ) {
// Вывод в консоль данных.
//Serial.println( "GSM status = READY" );
Serial.print( "T = " );
Serial.print( currentTemperature );
Serial.print( "\nH = " );
Serial.print( currentHumidity );
delay( 2000 );
//needSend = false;
return true;
//}
//return false;
}
void setup() {
delay( 1000 );
Serial.begin( 9600 );
Serial.println( "Prepare to task..." );
needSend = 1;
}
void loop() {
if ( needSend ) {
Serial.println( "Starting task..." );
// В обработчике Watchdog таймер установился флаг GSM-задания.
needSend = 0;
// Отключает сторожевой таймер.
off_WDT();
// Инициализация GSM модема
Serial.println( "Testing GSM..." );
// Проверка модема.
if ( gsm.begin( 2400 ) ) {
// Вывод в консоль данных.
Serial.println( "GSM status = READY" );
createSample();
int counter = 0;
// Попытка отправданных.
while ( true ) {
if ( !send() ) {
counter++;
}
if (counter == 4) {
counter = 0;
needSend = 1;
// Выход из цикла отправки.
break;
}
break;
Serial.println( "Sended." );
}
}
// Усыпляет GSM-модуль.
// Включает сторожевой таймер.
setup_WDT();
}
Serial.println( "Prepare to sleep." );
// Усыпляем Атмегу
sys_sleep();
}
Он работал, каждые пять минут делал замеры и отправлял их в консоль.
Далее я захотел, чтобы он отправлял еще и показатель замера напряжения.
Для снятия показателя использовал этот код:
http://mk90.blogspot.com/2009/06/vcc.html
Отдельно все работало. Потом я их объединил и получил вот что:

Последняя фраза циклится.
Что сделал, чтобы исправить: вернул на место, чтобы считывались пины до 7-го в core:
ADMUX = (analog_reference << 6) | (pin & 0x07);
Перезагрузил IDE, заново откомпилировал скетч, без изменений с батареей, снова загрузил в ардуину. Никакого эффекта.
Кто-то может подсказать?
По ссылке - меняется:
может оно у Вас куда сползло?
И я бы добавил отладочных принтов в функцию sys_sleep() - чтобы понять: где оно там ломается... Хотя, у Вас в двух местах встречается "
Prepare to"...void loop() { if ( needSend ) { Serial.println( "Starting task..." ); // В обработчике Watchdog таймер установился флаг GSM-задания. needSend = 0; // Отключает сторожевой таймер. off_WDT(); // Инициализация GSM модема Serial.println( "Testing GSM..." ); // Проверка модема. if ( gsm.begin( 2400 ) ) { // Вывод в консоль данных. Serial.println( "GSM status = READY" ); createSample(); int counter = 0; // Попытка отправки данных. while ( true ) { if ( !send() ) { counter++; } if (counter == 4) { counter = 0; needSend = 1; // Выход из цикла отправки. break; } break; Serial.println( "Sended." ); } } // Усыпляет GSM-модуль. // Включает сторожевой таймер. setup_WDT(); Serial.println( "Timer WDT on." ); } Serial.println( "Sleep." ); // Усыпляем Атмегу sys_sleep(); }Добавил принты.
Видно, что ломается после вызова ф-и send.
Переделал так:
#include <avr/pgmspace.h> // Сериал порт. #include <SoftwareSerial.h> unsigned int minutes = 0; // Задаёт интервал сна устройства, в минутах. unsigned char SendIntervalInMinutes = 5; // Активация отправки. unsigned char needSend; volatile unsigned char WDT_wake; volatile unsigned char SleepTimeInSec = 60; // Обработчик прерываний по срабатыванию охранного таймера. ISR( WDT_vect ) { // Увеличит счетчик прерываний. static unsigned char WDT_counter; // Отсчет минут. if ( WDT_counter++ == SleepTimeInSec ) { WDT_counter = 0; if ( minutes++ == SendIntervalInMinutes ) { minutes = 0; // Флаг о необходимости выполнения задачи отправки данных. needSend = 1; } } asm ( "WDR" ); } void setup_WDT( void ) { asm ( "CLI" ); asm ( "WDR" ); // Сброс флага срабатывания. MCUSR &= ~( 1 << WDRF ); WDTCSR = ( 1 << WDCE ) | (1 << WDE ); // Настройка сторожевого таймера на период в 1 сек. // Перевод в режим работы генерирования прерываний. WDTCSR = ( 1 << WDP2 ) | ( 1 << WDP1 ) | ( 1 << WDIE ) | ( 1 << WDIF ); asm ( "SEI" ); } void off_WDT( void ) { asm ( "CLI" ); asm ( "WDR" ); // Сброс флага срабатывания. MCUSR &= ~( 1 << WDRF ); WDTCSR = ( 1 << WDCE ) | ( 1 << WDE ) | ( 1 << WDIF ); // Turn off WDT. WDTCSR = 0x00; asm ( "SEI" ); } void sys_sleep( void ) { asm ( "CLI" ); // Выключает АЦП. ADCSRA &= ~( 1 << ADEN ); // Конфигурирует режим power-down. SMCR = ( 1 << SE ) | ( 1 << SM1 ); asm ( "SEI" ); asm ( "SLEEP" ); } void sys_wake( void ) { // Конфигурация режима power-down. SMCR = 0x00; } void setup() { delay( 1000 ); Serial.begin( 9600 ); Serial.println( "Prepare to task..." ); } void loop() { off_WDT(); Serial.println( "Awake." ); setup_WDT(); Serial.println( "Sleep." ); sys_sleep(); }Что-то совсем грустное: