TDD (Test-Driven Development) Physical Traffic Light
Robert C. Martin (Uncle Bob) said in a talk:
Imagine you have a button that you can push, it will test your code and if
everything is working a green light will come up, but if something is broken,
a red light will come up […]
He was of course talking about TDD. It got me inspired to build this little
tool.
Hardware schematics, firmware and host software is available in this GitHub
repository. Along with information
on how to compile and use.
This is a physical toy traffic light to be used with software development TDD
(and testing in general) tools. It will not boost your productivity nor make
you a better programmer or TDD practitioner, but it looks cool :)
Hardware
The atmega328p AVR chip is very popular and cheap, so much so, that chances
are high you got it with the Arduino bootloader, which gets in the way as we can
perfectly use the internal oscillator at 1Mhz instead of an external 16Mhz
crystal. Fix this by changing the fuses:
# avrdude -p m328p -c usbasp -U lfuse:w:0x62:m -U hfuse:w:0xd9:m
The circuit is simple enough to mount in some perfboard. Additionally, I added
some small neodymium magnets in the back for mounting purposes.
Software
The firmware is no more than some UART boilerplate with a 4800
baud rate so
that it’s stable at 1MHz.
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1000000
#define BAUD 4800
#define BAUD_PRESCALE ((((F_CPU/16) + (BAUD/2)) / (BAUD)) - 1)
char getchar(void)
{
while ((UCSR0A & (1 << RXC0)) == 0) {}
return UDR0;
}
The main loop will wait for a command r
, y
or g
and turn on the pin
corresponding to the color LED.
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1000000
#define BAUD 4800
#define BAUD_PRESCALE ((((F_CPU/16) + (BAUD/2)) / (BAUD)) - 1)
char getchar(void)
{
while ((UCSR0A & (1 << RXC0)) == 0) {}
return UDR0;
}
Notice how if any other character is received the output gets cleared.
The host software configures the serial port with a 4800
baud rate:
void serial_init(char* port)
{
if (COM_FD > 0)
{
return;
}
// Open serial port file
int fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
// Configure serial port
struct termios config;
if (tcgetattr(fd, &config) != 0)
{
= -1;
COM_FD ("Error while configing serial port");
printf(1);
exit}
(&config, B4800);
cfsetispeed(&config, B4800);
cfsetospeed
.c_cflag |= (CLOCAL | CREAD | CS8);
config.c_cflag &= ~(PARENB | PARODD);
config.c_iflag = 0;
config.c_oflag = 0;
config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
config.c_cc[VTIME] = 5;
config.c_cc[VMIN] = 0;
config
if (tcsetattr(fd, TCSANOW, &config) != 0)
{
= -1;
COM_FD ("Error while configing serial port");
printf(1);
exit}
= fd; COM_FD
With that, controlling the LEDs is as simple as:
(COM_FD, "r", 1); write
Find more information about how to use it in the GitHub
repository.
Robert C. Martin (Uncle Bob) said in a talk:
Imagine you have a button that you can push, it will test your code and if everything is working a green light will come up, but if something is broken, a red light will come up […]
He was of course talking about TDD. It got me inspired to build this little tool.
Hardware schematics, firmware and host software is available in this GitHub repository. Along with information on how to compile and use.
This is a physical toy traffic light to be used with software development TDD (and testing in general) tools. It will not boost your productivity nor make you a better programmer or TDD practitioner, but it looks cool :)
Hardware
The atmega328p AVR chip is very popular and cheap, so much so, that chances are high you got it with the Arduino bootloader, which gets in the way as we can perfectly use the internal oscillator at 1Mhz instead of an external 16Mhz crystal. Fix this by changing the fuses:
# avrdude -p m328p -c usbasp -U lfuse:w:0x62:m -U hfuse:w:0xd9:m
The circuit is simple enough to mount in some perfboard. Additionally, I added some small neodymium magnets in the back for mounting purposes.
Software
The firmware is no more than some UART boilerplate with a 4800
baud rate so
that it’s stable at 1MHz.
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1000000
#define BAUD 4800
#define BAUD_PRESCALE ((((F_CPU/16) + (BAUD/2)) / (BAUD)) - 1)
char getchar(void)
{
while ((UCSR0A & (1 << RXC0)) == 0) {}
return UDR0;
}
The main loop will wait for a command r
, y
or g
and turn on the pin
corresponding to the color LED.
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1000000
#define BAUD 4800
#define BAUD_PRESCALE ((((F_CPU/16) + (BAUD/2)) / (BAUD)) - 1)
char getchar(void)
{
while ((UCSR0A & (1 << RXC0)) == 0) {}
return UDR0;
}
Notice how if any other character is received the output gets cleared.
The host software configures the serial port with a 4800
baud rate:
void serial_init(char* port)
{
if (COM_FD > 0)
{
return;
}
// Open serial port file
int fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
// Configure serial port
struct termios config;
if (tcgetattr(fd, &config) != 0)
{
= -1;
COM_FD ("Error while configing serial port");
printf(1);
exit}
(&config, B4800);
cfsetispeed(&config, B4800);
cfsetospeed
.c_cflag |= (CLOCAL | CREAD | CS8);
config.c_cflag &= ~(PARENB | PARODD);
config.c_iflag = 0;
config.c_oflag = 0;
config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
config.c_cc[VTIME] = 5;
config.c_cc[VMIN] = 0;
config
if (tcsetattr(fd, TCSANOW, &config) != 0)
{
= -1;
COM_FD ("Error while configing serial port");
printf(1);
exit}
= fd; COM_FD
With that, controlling the LEDs is as simple as:
(COM_FD, "r", 1); write
Find more information about how to use it in the GitHub repository.