Esempio n. 1
0
int
main( int argc, char **argv )
{
	int i;

	for (i = 1; i < argc; i++) {
		char *val = argv[i];
		struct tst *timer = nfmalloc( sizeof(*timer) );
		init_wakeup( &timer->timer, timed_out, timer );
		init_wakeup( &timer->morph_timer, morph_timed_out, timer );
		timer->id = ++nextid;
		timer->first = strtol( val, &val, 0 );
		if (*val == '@') {
			timer->other = timer->first;
			timer->first = strtol( ++val, &val, 0 );
		} else {
			timer->other = -1;
		}
		if (*val == ':') {
			timer->morph_to = strtol( ++val, &val, 0 );
			if (*val != '@')
				goto fail;
			timer->morph_at = strtol( ++val, &val, 0 );
		} else {
			timer->morph_at = -1;
		}
		if (*val) {
		  fail:
			fprintf( stderr, "Fatal: syntax error in %s, use <timeout>[@<delay>][:<newtimeout>@<delay>]\n", argv[i] );
			return 1;
		}
		timer_start( timer, timer->first );
		if (timer->morph_at >= 0) {
			printf( "timer %d, should morph after %d\n", timer->id, timer->morph_at );
			conf_wakeup( &timer->morph_timer, timer->morph_at );
		}
	}

	main_loop();
	return 0;
}
int main(void)
{
	uint8_t i;
	uint16_t wakeup_sec;
	bool send;

	// delay 1s to avoid further communication with uart or RFM12 when my programmer resets the MC after 500ms...
	_delay_ms(1000);

	util_init();
	
	check_eeprom_compatibility(DEVICETYPE_SOILMOISTUREMETER);
	
	// configure power pin for 74HC14D as output
	sbi(TRIGGERPWR_DDR, TRIGGERPWR_PIN);

	// read packetcounter, increase by cycle and write back
	packetcounter = e2p_generic_get_packetcounter() + PACKET_COUNTER_WRITE_CYCLE;
	e2p_generic_set_packetcounter(packetcounter);

	// read device id
	device_id = e2p_generic_get_deviceid();

	dry_thr = e2p_soilmoisturemeter_get_drythreshold();
	if (dry_thr == 0) // set default value if never initialized
	{
		dry_thr = 40000;
	}

	counter_min = e2p_soilmoisturemeter_get_minval();
	if (counter_min == 0) // set default value if never initialized
	{
		counter_min = 30000;
	}

	avgIntInit = e2p_soilmoisturemeter_get_averagingintervalinit();
	avgInt = e2p_soilmoisturemeter_get_averaginginterval();
	smoothing_percentage = e2p_soilmoisturemeter_get_smoothingpercentage();

	osccal_init();

	uart_init();

	UART_PUTS ("\r\n");
	UART_PUTF4("smarthomatic Soil Moisture Meter v%u.%u.%u (%08lx)\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_HASH);
	UART_PUTS("(c) 2014..2015 Uwe Freese, www.smarthomatic.org\r\n");
	osccal_info();
	UART_PUTF ("DeviceID: %u\r\n", device_id);
	UART_PUTF ("PacketCounter: %lu\r\n", packetcounter);
	UART_PUTF ("AveragingInterval for initialization: %u\r\n", avgIntInit);
	UART_PUTF ("AveragingInterval for normal operation: %u\r\n", avgInt);
	UART_PUTF ("Dry threshold: %u\r\n", dry_thr);
	UART_PUTF ("Min value: %u\r\n", counter_min);
	UART_PUTF ("Smoothing percentage: %u\r\n", smoothing_percentage);

	adc_init();

	// init AES key
	e2p_generic_get_aeskey(aes_key);

	// set pull-up for BUTTON_DDR
	sbi(BUTTON_PORT, BUTTON_PIN);
	_delay_ms(10);

	// set DIDR for all ADC channels and AINs, switch off digital input buffers to reduce ADC noise and to save power
	DIDR0 = 63;
	DIDR1 = 3;
	
	// If button pressed at start up, go to sleep for idle power consumption test.
	// Don't communicate with RFM12, which may not have been connected yet.
	if (BUTTON)
	{
		led_blink(50, 50, 20);
		power_down(true);
	}

	led_blink(500, 500, 3);

	rfm12_init();
	wakeup_sec = init_wakeup();

	// init interrupt for button (falling edge)
	sbi(EICRA, ISC11);
	sbi(EIMSK, INT1);
	
	sei();

	for (i = 0; i < SEND_STATUS_TIMES_AT_STARTUP; i++)
	{
		prepare_deviceinfo_status();
		send_prepared_message();
		_delay_ms(800);
		prepare_battery_status();
		send_prepared_message();
		_delay_ms(800);
	}

	while (42)
	{
		if (BUTTON)
		{
			led_blink(100, 0, 1);
			UART_PUTS("Button pressed!\r\n");
			
			uint8_t cnt = 0;
			
			while (BUTTON && (cnt < 250))
			{
				_delay_ms(10);
				cnt++;
			}
			
			if (cnt == 250)
			{
				UART_PUTS("Long press -> initiate measure mode!\r\n");
				
				while (BUTTON)
				{
					led_blink(100, 100, 1);
				}

				init_mode = true;
				wupCnt = 0;
				counter_meas = 0;
				init_wakeup(); // to usually shorter value
				
				UART_PUTS("Button released!\r\n");
				_delay_ms(10);
			}
		}
		else
		{
			send = true;

			//UART_PUTF("version_status_cycle = %u\r\n", version_status_cycle);
		
			if (!measure_humidity())
			{
				if (battery_status_cycle > 0)
					battery_status_cycle--;

				if (version_status_cycle > 0)
					version_status_cycle--;

				if (version_status_cycle == 0)
				{
					version_status_cycle = SEND_VERSION_STATUS_CYCLE;
					prepare_deviceinfo_status();
				}
				else if (battery_status_cycle == 0)
				{
					battery_status_cycle = SEND_BATTERY_STATUS_CYCLE;
					prepare_battery_status();
				}
				else
				{
					send = false;
				}
			}

			if (send)
			{
				send_prepared_message();
			}
		}
		
		power_down(true);
	}
	
	// never called
	// aes256_done(&aes_ctx);
}
// Measure humidity, calculate relative value in permill and return it.
// Return true, if humidity was sent.
bool measure_humidity(void)
{
	bool res = false;
	uint16_t cnt;
	
	switch_schmitt_trigger(true);
	_delay_ms(10);

	// make PD5 an input and disable pull-ups
	DDRD &= ~(1 << 5);
	PORTD &= ~(1 << 5);

	// clear counter
	TCNT1 = 0x00;

	// configure counter and use external clock source, rising edge
	TCCR1A = 0x00;
	TCCR1B |= (1 << CS12) | (1 << CS11) | (1 << CS10);

	_delay_ms(100);

	//cnt = (TCNT1H << 8) | TCNT1L;
	cnt = TCNT1;

	TCCR1B = 0x00; // turn counter off
	
	switch_schmitt_trigger(false);
	
	counter_meas += cnt;
	wupCnt++;
	
	UART_PUTF4("Init mode %u, Measurement %u/%u, Counter %u\r\n",
		init_mode, wupCnt, init_mode ? avgIntInit : avgInt , cnt);

	if ((init_mode && (wupCnt == avgIntInit)) || (!init_mode && (wupCnt == avgInt)))
	{
		uint32_t avg = init_mode ? counter_meas / avgIntInit : counter_meas / avgInt;
		
		if (init_mode)
		{
			UART_PUTF("Init: Save avg %u as dry threshold.\r\n", avg);
			dry_thr = avg;
			counter_min = dry_thr - 1;
			init_mode = false;
			init_wakeup(); // to normal value
			e2p_soilmoisturemeter_set_drythreshold(dry_thr);
		}
		else
		{
			int32_t result;
		
			if (avg < counter_min)
			{
				counter_min = avg;
				UART_PUTF("New min: %lu, ", counter_min);
			}
		
			if (avg > dry_thr)
			{
				result = 0;
			}
			else
			{
				result = (dry_thr - avg) * 1000 / (dry_thr - counter_min);
			}
		
			UART_PUTF("Avg: %u, ", avg);
			UART_PUTF("Result: %lu permill\r\n", result);
			
			// Don't change reported value if it changes within a window of
			// some percent.
			if (reported_result == 0)
			{
				reported_result = result;
			}
			else
			{
				if (direction_up)
				{
					if (result > reported_result)
					{
						reported_result = result;
					}
					else if (result < reported_result - smoothing_percentage * 10)
					{
						reported_result = result;
						direction_up = false;
					}
				}
				else // direction down
				{
					if (result < reported_result)
					{
						reported_result = result;
					}
					else if (result > reported_result + smoothing_percentage * 10)
					{
						reported_result = result;
						direction_up = true;
					}
				}
			}
			
			prepare_humidity_status((uint16_t)reported_result);
			//prepare_humidity_status_RAW_DBG((uint16_t)reported_result, (int16_t) MIN((int32_t)avg, 30000)); // for debugging only
			res = true;
		}

		wupCnt = 0;
		counter_meas = 0;
	}
	
	_delay_ms(10);
	return res;
}