Feed on
Posts
Comments

From our previous post, we took on the task to build our own alarm system and have the PIR, door sensor and some of the server code built. In this part we’ll add the remote and look at some attempted improvements.

https://www.youtube.com/watch?v=MYtkCsHhZ0Y
(sneak peak of remote, PIR,  siren and server all working together)

For the remote control, all that’s required is two buttons for alarm on and off plus an LED to show when the button is pressed.

// Increment our 256bit random number
...

// Generate the random block (160 bit) using SHA1 from our random number
sha1(data_out, random_number, 256);

// Set data_out to say we are a remote control
data_out[SENSOR_TYPE] = REMOTE_CONTROL;
data_out[REMOTE_REQUEST] = REMOTE_ROLLING_CODE;

// Check in the with server
if (check_in()) {
	...
	// On or off?
	data_out[SENSOR_TYPE] = REMOTE_CONTROL;
	data_out[REMOTE_REQUEST] = system_state;

	// Generate the new rc code to use and generate the SHA1 block (160 bit) from our rc code
	rc_code_init(rc_code_addition);
	sha1(data_out, rc_code, 128); // SHA1 of our rolling code

	// Transmit a few times to ensure the server gets it
	...
}

We can use the same PIR code to send a random SHA1 block, receive the rolling code addition which will be 32bit this time to cover switching the on/off alarm a lot of times and then we’ll quickly send the rolling code a few times.

// 128bit rolling code for remote control (you should change this, each device should be different)
prog_char rc_code_base[] PROGMEM = {0xD8, 0xBF, 0xE9, 0x55, 0x9E, 0x32, 0xA7, 0x69, 0x01, 0xEB, 0x8B, 0x62, 0xB7, 0x50, 0x41, 0x9F};
uint8_t rc_code[16];
uint32_t rc_code_addition = 0;

// Initalise the random number and increment until the end
void rc_code_init(uint32_t rand_end) {
	for (int x = 0; x < 16; x++) {
		rc_code[x] = pgm_read_byte(&rc_code_base[x]);
	}
	for (int x = 0; x < rand_end; x++) {
		...
	}
}

One improvement we can make to all sensors is to use PGM to store the base rolling code and initialise it when needed.

// Power up the nRF24L01
TX_POWERUP;
_delay_ms(3);

// Send a request with the random number
if (!mirf_transmit_data()) { return 0; }

// Sleep 16ms for the server to generate the HMAC
watchdog_sleep(T16MS);

// Receive the response
if (!mirf_receive_data()) { return 0; }

// Power down the nRF24L01
POWERDOWN;

Another small improvement is that we’ll only power up when we have something to send or receive and powerdown straight after. Also now that the server is running at 12MHz it only takes approximately 15ms (down from 250ms) for the server to generate the HMAC from our random block so that should help decrease power consumption.

After some testing, on the server, we can reduce the listen/transmit wait times from 200ms to 25ms so now the time it takes the server to process a request should really be down to 65ms or less.

I wanted to make this a bit better, so I started looking at how to reduce the sensor check in time. My idea was to have each sensor have the same random number, each sensor to have it’s own special range before the random number and to have the server send out a time so that each sensor could sync up with the server. The client/server would then take the time and divide it by 10, it would give each side which random number to use and give it up to 10 seconds to be out of sync. This would allow us to do 1 update to generate the new HMAC every 10 seconds.

The problem was this approach was that if you go out of sync, you don’t have any real way to get back into sync unless you would use up the sensor’s own special range which is used for reporting movement. There is also the off chance that during the use of the special range that the addition number which keeps the server and client is sync too to go out of sync, where both sides acknowledge each other but one of them fails. In the end I found that going back to the older style which each sensor has it’s own random number was the simpler and better choice.

I’ve now got everything working relatively well, now it’s just a matter of putting it all together on some PCBs and leaving it on for a few days for testing, might take a few weeks to have it all up and running. One issue is that the remote control will probably end up being larger than the ones I’ve got already.

Part 1
Part 2: Two way communication for PIR sensors
Part 3: Secure communication
Part 4: Adding on sirens and SMS sending
Part 5: Modifying the PIR sensor
Part 6: PIR PCB
Part 6.5: PCBs arrived
Part 7: See which sensors check-in
Part 8: Building our own alarm system
Part 9: Remote control and attempted improvements
Part 10: Prototype PCBs

Leave a Reply