One wire configurator

Those who are using Arduino for developing micro-controller based applications often faced the situation where multiple options must be evaluated from the same main sketch. Say for example that you want to evaluate various timing values for the famous “blink” sketch. The code translation for this will consist in defining a global variable that will be changeable by means of external interaction. Here is a list of options along with their pros and cons:

Option Pros Cons
Commands through serial port (Almost) unllimited number of commands Requires an additional library and a display or control console
Keyboard High number of combinations Requires an additional library and a display or control console for better control
Switches Simple setup Requires multiple pins, switches, limited number of combinations
Rotary encoder Requires only three pins Requires an additional library and a display or control console

An alternative to these methods is the use of a simple wire strap and few lines of code. While a basic use of 5 pins from one port lead to the potential use of  5 switches, using on single wire will allow 10 combinations. Taking for instance PORTB pins 0 to 4  (so as to say digital pins 8, 9, 10, 11 and 12), the combinations shall be:

  • 1: 0 and 1
  • 2: 0 and 2
  • 3: 0 and 3
  • 4: 0 and 4
  • 5: 1 and 2
  • 6: 1 and 3
  • 7: 1 and 4
  • 8: 2 and 3
  • 9: 2 and 4
  • 10: 3 and 4

The “no strap” condition adds an extra eleventh combination (combination “0”).

Sensing the strap if pretty easy. It consists in setting one reference pin to a certain level (actually ground) and sensing the other pins in order to detect whether or not one of these pins is attached to the reference pin. This process is applied to each in from the selected port. The code example below illustrates the process described above and applies to pins 0 to 4 from PORTB.

uint8_t DecodedStapPosition(void) 
/* decode strap coding */
{
	/* Local constants */
	const uint8_t positions = 5; /* Number of pins to be scanned */
	const uint8_t mask = ((1 << positions) - 1); /* Pins mask */
	uint8_t	counts = 0; 
	uint8_t result = counts; /* Set the default result (no strap) */
	for (uint8_t i = 0; i < positions; i++) {
		/* make all pins input pins except the driving pin "i" */
		DDRB &= ~mask;
		DDRB |= (1 << i);
		/* bias all pins to VCC except the driving pin "i" */
		PORTB |= mask;
		PORTB &= ~(1 << i);
		/* check the state of the other pins */
		for (uint8_t j = (i + 1); j < positions; j++) {
			counts += 1;
			/* read pin states */
			if (~PINB  & (1 << j)) {
				result = counts;
			}
		}
	}
	return(result);
}

Implementing this function is very easy and could be used in this way

/*
  Modified Blink
  Turns on an LED on for one second, then off for a variable time, repeatedly.

  This example code is in the public domain.
 */

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
int pause = 500;
// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
	/* Read pins state */
	switch (DecodedStapPosition()) {
	/* Stand alone functions */
	case 0: pause = 500; break;
	case 1: pause = 10; break;
	case 2: pause = 20; break;
	case 3: pause = 40; break;
	case 4: pause = 80; break;
	case 5: pause = 160; break;
	case 6: pause = 320; break;
	case 7: pause = 640; break;
	case 8: pause = 1280; break;
	}

	digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
	delay(pause);               
	digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
	delay(pause);               
}

uint8_t DecodedStapPosition(void) 
/* decode strap coding */
{
	/* Local constants */
	const uint8_t positions = 5; /* Number of pins to be scanned */
	const uint8_t mask = ((1 << positions) - 1); /* Pins mask */
	uint8_t	counts = 0; 
	uint8_t result = counts; /* Set the default result (no strap) */
	for (uint8_t i = 0; i < positions; i++) {
		/* make all pins input pins except the driving pin "i" */
		DDRB &= ~mask;
		DDRB |= (1 << i);
		/* bias all pins to VCC except the driving pin "i" */
		PORTB |= mask;
		PORTB &= ~(1 << i);
		/* check the state of the other pins */
		for (uint8_t j = (i + 1); j < positions; j++) {
			counts += 1;
			/* read pin states */
			if (~PINB  & (1 << j)) {
				result = counts;
			}
		}
	}
	return(result);
}

In the end we get a pretty versatile combination setting system, to the cost of one piece of wire and few lines of code!

strap

HTH

 

 

 

Leave a Reply

You must be logged in to post a comment.