Поломал UNO

Prin53
Offline
Зарегистрирован: 31.12.2013

Есть работающий код:

// Для работы с сим-картой.
#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, заново откомпилировал скетч, без изменений с батареей, снова загрузил в ардуину. Никакого эффекта.

Кто-то может подсказать?

 

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

По ссылке - меняется:

analogReference(DEFAULT);                   // использовать Vcc как AREF

может оно у Вас куда сползло?

И я бы добавил отладочных принтов в функцию sys_sleep() - чтобы понять: где оно там ломается... Хотя, у Вас в двух местах встречается "Prepare to"...

Prin53
Offline
Зарегистрирован: 31.12.2013
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();
}

Что-то совсем грустное: