Week #14: Input devices

Our tasks for the fourteenth week were:
  1. Measure something: add a sensor to a microcontroller board that you have designed and read it
Instead of using a premade sensor, I chose to build a sensor that would be fundamental to my final project, the Recoiler. Since one of the purposes of the device is to measure the recoiled wire length, an indirect way of measuring it would be by counting the number of turns of the reel.

It's not a perfect measurement, though. Since the wire has the liberty to move along the lenght of the reel and due to the fact that the diameter of the already coiled portion increases as the recoiling continues, this measurement underestimates the actual length. But, this does not pose an issue for my final project because it's actually good if I always recoil a little more wire, just for safety (for example, if a group of students breaks the wire insulation during a class experiment).

To count the reel turns, I could've used a limit switch, like the one shown below.

Limit switch

But, I really embraced the DIY spirit on this one and chose to build a different sensor. It's quite simple: I inserted a piece of wire into the component I built to adapt the DC motor axis to the reel (the design and assembly is documented on Week 2 assignment).

Drilling a hole  Inserting the wire

The idea I had in mind was doing something similar to slot cars: as the copper strands slide along a pair o metal rails, the circuit is closed. These are the metal rails:

Rails   Rails

One of these rails (staples, to be more precise) is connected to the microcontroller +5V output and the other, to an input pin. Then, by continuosly reading this input pin state, one can count the number of turns.

The first time I did this, I used an Arduino Uno, since the microcontroller PCB I designed wasn't working. This is the setup I tried at first:

First assembly

For the initial tests, I used a code that would turn on the built in LED everytime the circuit is closed (when the copper strands touch both rails simultaneously, as shown by the following image) and off when the circuit is open.

Closed circuit

This is the code:

const int medidor = 5;

int estado_medidor = LOW;

 

void setup() {

  pinMode(medidor, INPUT);

  pinMode(LED_BUILTIN, OUTPUT); 

}

 

void loop() {

  estado_medidor = digitalRead( medidor );

  if (estado_medidor == HIGH) {

    digitalWrite(LED_BUILTIN,HIGH);

  } else {

    digitalWrite(LED_BUILTIN,LOW);

  }

}


Then, I hit a bump on the road, a problem that cost me at least 2 days to figure out how to solve. During the tests, the assembly could always correctly detect a closed circuit: as soon as I touched the copper strands on both rails, the built in LED would light up. But, after removing the wire, the built in LED would remain lit for a few seconds. Not only that, but it would also light up randomly, even when the copper strands were not touching the rails.

After rebuilding the system several times, I couldn't, for the life of me, solve this problem. Then, I stopped trying to just connect wires and took some time studying the issue. The answer was here, but I'll write it here anyway.

Both AtMega and AtTiny microcontrollers have pins that, when configured as inputs with nothing connected to them, will report random changes in the pin state, due to electrical noise of the adjacencies or capacitive coupling with a nearby pin. So, that's the reason why the assembly could correctly detect a high level but not a low one, and this also explains why the built in LED remained lit even after the circuit was opened: it was due to a capacitor being charged and, during it's discharge, the microcontroller would wrongly read the small residual voltage as a high level.

So, if I wanted the microcontroller to correctly interpret a low level, I would need to ensure that the pin voltage was a true zero, unlike electrical noise. And this is exactly the job of a pull-down resistor: by connecting the input pin to GND through a high-resistance resistor, which allows very little current to flow, we make sure that the electrostatic potential on both pins is the same (no current means no potential difference!). Since one of them is GND (in this case, 0V), the input pin is "forced" to achieve 0V potential.
 
And, as soon as I learned that, I also realized this was something I should have learned a long time ago: on Week 6 assignment, most tutorials I read said something about pull-up and pull-down resistors, but I guess I wasn't ready to learn that then. Well, better late than never, right?

After this journey of discovery, this was my new assembly:

Second assembly

And it worked perfectly! As soon as I touched the copper strands on the rails, the built in LED would light up; at the moment I opened the circuit, the LED would turn off. Perfect!

After I got my microcontroller PCB working (you can read about that odissey on Week 10 assignment), I tested this setup again, but with my PCB instead of Arduino. But, since my PCB did not have a built in LED, I used serial communication to check if it was working. This is the new code:

const int medidor = 5;

int estado_medidor = LOW;

 

void setup() {

  pinMode(medidor, INPUT);

  Serial.begin(9600);

}

 

void loop() {

  estado_medidor = digitalRead( medidor );

  if (estado_medidor == HIGH) {

    Serial.println(1);

  } else {

    Serial.println(0);

  }

  delay(50);

}

And it worked just fine! As long as I kept the copper strands touching the rails, the serial monitor would show a sequence of 1's; as soon as I opened the circuit, it would show a sequence of 0's.

Serial communication to test the assembly

And that's what I got for Week 14 assignment! This contraption was effectively used on my final project.