DIY Roomba virtual wall (part 2)
Previous tests based on Arduino were quite promising so I decided to make a ready-to-use device and test it in field (ehm.. at home:)). In this article I would like to describe the Virtual Wall-like device mounted on dedicated PCB. This article also includes results of field-tests of the IR transmitter.
Introduction
At the beginning I would like to say that I haven't designed new PCB for the device from the scratch. Since those are still tests, I have reused a previously designed PCB which was used as a sensor board for BTMS. Source code is however written from the scratch. In general just few components were mounted on the PCB (mainly microcontroller (Atmega8A), some resistors, leds, one transistor to turn the IR led on/off and one tactile button). There was totally no need to install other components (at least not yet;)).
Description of hardware
So as described in the introduction on the PCB there are just few components. There was no need to install voltage regulator (ATmega8A accepts voltages up to 5V, so no issues here). There is a button installed which is connected to INT0 input of AVR. There are also two LEDs: one is used purely for user interaction and the second one blinks in the same manner as main IR led. Currently this LED is a red LED however it might be replaced with the SMD IR LED as well (actually currently I am thinking about this). The main IR transmitting LED is turned on/off through a mosfet. This could be avoided (and LED could be connected directly to AVR) but this might be useful when using more LEDs (as an example).
This is the layout of the PCB and components:
How does it actually work? (a.k.a. user's manual)
In general usage of the transmitter is very very easy. After turning the power supply the IR LED starts to transmit the pattern gathered previously (see part 1) for 15 minutes. After that time the transmitter will turn off and go to sleep mode (no power consumption at all!). When one needs to have the virtual wall working for more than 15 minutes, just simply click the button. Every click increments the work time by 15 minutes. So click three more times to have the wall operating for an hour. Every few seconds the blue LED will blink. Number of blinks says how many 15 minutes blocks (quarters) are still "left" to the moment when the wall turns off:
- 1 blink: Wall will turn off in less than 15 minutes
- 2 blinks: Wall will turn off in 15-30 minutes
- 3 blinks: Wall will turn off in 30-45 minutes
- 4 blinks: Wall will turn off in 45-60 minutes
- ... and so on
To turn the wall off earlier than this, simply push and hold the button until the blue led lits without blinking. Then release the button. After that the wall will turn off immediately. Simple, isn't it? :)
it is worth to mention that the transmitter doesn't use any power when it is in the sleep mode. Thanks to that there is no risk that the DIY wall will drain batteries when not used but left unattended. It is perfectly safe and ok to leave the wall PCB connected to the power supply all-time-long.
Description of the software
Whole Atmega8A load was written in C and fits in one file (and something like 1kB of flash memory (out of 8kB available!)). In general whole code is written using timers and interrupts. I thought this would be a good approach for time-sensitive device.
Here you can find the source code of the transmitter: https://bitbucket.org/tomeczko/virtual-wall
Short description of routines:
- ISR(INT0_vect) - interrupt routine for button - responsible for incrementing the remaining time by 15 minutes. incrTimeoutByButton protects against multiple increment as a result of key boncing (software debouncing).
- ISR(TIMER2_COMP_vect) - interrupt routine for TIMER2 compare match. TIMER2 is used for triggering start of patterned IR transmission (second "if") and counting time (first "if").
- ISR(TIMER0_OVF_vect) - interrupt routine for TIMER0 overflow. TIMER0 is used for turning on/off the modulation of IR LED. Global variable code contains a pattern to be transmitted using IR LED.
- main():
- Initialization part:
- Activation of internal pull-up on INT0 line.
- Configuration of TIMER1. TIMER1 is used to modulate the IR LED at 38kHz.
- Configuration of TIMER0 and TIMER2. Also configuration of LED outputs.
- While loop - event happens only when there was a trigger from TIMER2:
- Decrementation of turn-off timer.
- Blinking the blue LED (that many times as needed).
- Turn-off routine. Here note: INT0 must be switched to "level-triggered" from "edge-triggered" to be able to wake up from sleep (changes in MCUCR).
- "Reinitialization" routines after wake-up (setting INT0 to "edge-triggered", setting default timeout, etc).
- Initialization part:
Future things to be checked
- Would it be useful to use second IR LED (SMD) instead of red LED to have something similar to original Virtual Wall? (just to remind: original Virtual Wall has two IR transmitters: one is omnidirectional and uses one IR pattern, and the second one is a directional IR LED and uses second pattern).
- Does the IR LED pattern for directional LED in original Virtual Wall change when Roomba approaches the transmitter?
Update from 2017-08-23:
Roomba is quite sensitive regarding timing of infrared signal. Unfortunately on the PCB there is no place for crystal to clock the CPU so internal RC oscillator is used right now. I've noticed that after a time (few months) the RC time-constant looks a bit different and I had to update timing (update constants in source code, recompile and upload binary code to Atmega8) to make the wall working again.
http://eka.tomeczko.pl/index.php/diy-roomba-virtual-wall/8-diy-roomba-virtual-wall-part-2