Week 11 - Output Devices

Assignment

Individual assignment

add an output device to a microcontroller board you’ve designed, and program it to do something

Group assignment

measure the power consumption of an output device

Link to group page

Process

Choosing and testing output devices

For the purposes of my final project I wanted to test actuators that could make sound and motion. Specifically, I needed something that could make controlled buzzes (possibly with tones) and something that could make vibrations.

For buzzing, in our lab I found a package containing a series of little speakers like the one in the image below.

speaker

The only indication found on it were regarding its max power consumption of 0.25w and resistance of 8ohm. After plugging one of its wires to a pin of an arduino board, I made a simple script that rapidly changed the logical status of the pin, hence varying the pressure of the speaker membrane. In this way I was able to produce a series of creepy ticks that confirmed the functioning of the speaker.

speaker testing

Concerning a vibrating actuator, I found in our lab a series of little vibration generators which I considered not powerful enough for my final intentions (I was looking for something that could shake vehemently large objects) and so I opted to adapt a dc motor for this purpose.

motor

This motor came in with no information at all, so it depended entirely on me to find out what it could or couldn’t do.

Similarly to before, I applied 5 volts routed from an Arduino board to the the motor wires and experienced that it indeed started moving.

motor testing

After some web research, I found out that similar looking products can bear up to 12v of tension.

Designing a board

To fulfill the assignment, I started designing a board that could operato the actuators of my choice after a certain input.

The following schematic is inspired by the boards designed by Neil Gershenfeld for his Output Devices lesson.

schematics

In this board, a ATmega328 controls an analog signal a N-mosfet for operating the speaker and two PWM signals to operate the driver for the dc motor. Furthermore, I made it feature an input source, which is nothing more but the FSR sensor tested in the previous week.

As it’s possible to see in the board layout before, I’ve provided four double connectors to the board: two for the output devices, one for the input device and one for the power supply.

board

In Neil’s experiments, he uses an external power supply of 9v for both actuators so I opted for this solution as well (this is particularly handy, because you can simply plug in an easy-to-find 9v battery to the board and you’re ready to go).

Failure and a shortcut

It seems like I learned little to nothing from the mistakes of the previous week, and in fact after I milled and soldered my board I figured out an issue that hit me like a bad blow below the belt.

I wasn’t able to flash anything on my board.

The infamous “RC=-1” error message popped up at all of my programming attempt, to the point of almost dcriving me crazy and seeing it even in my sleep.

I couldn’t envise the reason at all, because after many, many checks everything seemed to be just fine in theory, but wasn’t working in reality. I desoldered, tested and soldered back every single piece of the board, with no improvements and in the end - driven both by frustration and hastiness - I opted once again to resort to the Arduino board to test my system.

(days after the end of the assignment I figured out what was not working on my board: nothing. In fact, the issue was in the cable I was using to connect programmer and board, since it was improperly crimped and wasn’t communicatin on few wires. To avoid the use of very, very bad cussings and prophanities, I’ll stop talking of this topic right now and will never ever mention it again in the future. Better if you don’t as well…)

arduino setting

Luckily I had at my disposal all the components I needed in the packaging for a breadboard, so I plugged everything in the same way of the board I envisioned and started to make scripts for testing the various parts.

First of all, I needed a function to read the values prompted by the FRS, and the Arduino library function map does so just finely.

int fsrRead() {
  return map(analogRead(fsrPin), 0, 1023, 0, 255);
}

This simple line alone provides all that is necessary to convert an analog input (converting it to a value from 0 to 1024) to an analog output (converting it to a value from 0 to 255). To be precise, the Arduinos (and all AVRs) analog outputs signals are nothing more than PWM signals, meaning a precisely-timed series of logical highs and lows that effectively are read as analog signals. I found the Wikipedia article about it very complete and well-articulated, if you need to delve in.

For my purpose, all I needed to do was to feed the value from map to the actuators pins with the analogWrite function.

In the following clip I’m directly controlling the speaker with the FSR sensor:

controlling speaker

And here I’m controlling the DC motor:

controlling motor

Program the board

The following code makes my system to be operated and analogically controlled by the FSR input device. I also added several serial communication functions so to see in real time what was going inside the controller.

int speakerPin = 6;
int motorPin = 11;
int directionPin1 = 10;
int directionPin2 = 9;
int fsrPin = A0;

int serialFlag = 0;

int motorThreshold = 192;
int speakerThreshold = 64;

bool motorFlag = false;
bool speakerFlag = false;;

void setup() {
// Serial communication init
Serial.begin(9600);

// Pins init
pinMode(fsrPin, INPUT);
pinMode(speakerPin, OUTPUT);
pinMode(motorPin, OUTPUT);
pinMode(directionPin1, OUTPUT);
pinMode(directionPin2, OUTPUT);

//invert value to turn the dc shaft it the other direction
//set to the same value to brake the motor
digitalWrite(directionPin1, LOW);
digitalWrite(directionPin2, HIGH);

analogWrite(motorPin, 0);
}

int fsrRead() {
  int tmp = analogRead(fsrPin);

  //check to avoid serial monitor dumping
  if (tmp != serialFlag) {
    Serial.print("Input value of ");
    Serial.print(tmp);
    tmp = map (tmp, 0, 1023, 0, 255);
    Serial.print(" mapped for output as ");
    Serial.println(tmp);
    serialFlag = tmp;
    }
    return tmp;
}

void checkForOutput(int readValue) {
  
  //if pressure is slight nothing happens
  //if it's medium, a modulated buzz begins
  // if it's heavy, the motor runs
  if (readValue >= speakerThreshold or speakerFlag) {
    if (readValue >= motorThreshold or motorFlag) {
      analogWrite(motorPin, readValue);
      motorFlag = true;
    
      //turns off motor if FSR below threshold
      if (readValue < motorThreshold) {
        motorFlag = false;
        analogWrite(motorPin, 0);
      }
    }
    analogWrite(speakerPin, readValue);
    speakerFlag = true;
    
    //turns off speaker if FSR below threshold
    if (readValue < speakerThreshold) {
      speakerFlag = false;
      analogWrite(speakerPin, 0);
    }
  }
}

void loop() {
  checkForOutput(fsrRead()); 
  delay(250); //slows down serial communication 
}

And the following clip is how it all worked:

good result

My own boards

For the purpose of the final I project I ended up using a customized DC motor, meaning that I applied a load I designed myself to create an eccentric movement and hence a vibration.

custom dc

To operate it and to keep the core board the cleanest as possible, I devised a separated board with driver, power supply, connectors and little more on it.

driver board

In this way, if I ever want to control a DC motor, I only have to plug this board to any two PWM pins of a controller and let it run. In fact, this idea was particularly helpful when I wasn’t still sure of the final layout of my system and the various parts were still just placeholders or floating all over desktops, backpacks and other people prototypes.

I did the same thing for the controlling the speaker, which actually for practical reasons has become a buzzer, but in its case - since I wanted more control - I designed its own dedicated controller which later I would command through I2C communication.

speaker board

Result

In the following clip, I used the board designed for the final project (also used in the previous week assignment) connected to the driver board and the customized DC motor.

motor vimeo

Specifically, I wanted to test how the motor reacted to different values and so I flashed the following code, which increments the power of 20% at each cycle.

#define dc1 5
#define dc2 6

void setup() {
pinMode(dc1, OUTPUT);
pinMode(dc2, OUTPUT);
analogWrite(dc2, 0);
}

void loop() {
  for (int i = 1; i < 5; i++) {
    analogWrite(dc1, 50 * i);
    delay(1000);
    analogWrite(dc1, 0);
    delay(1000);
    }
}

Similarly, I did with the speaker board.

speaker vimeo

This is the code I used to test it, onto which I variate the tone volume by 20% every half second.

#define speaker 1
#define highTone 255

void setup() {
	pinMode(speaker, OUTPUT);
}

void loop() {
  	for (int i = 1; i < 5; i++) {
 	analogWrite(speaker, highTone / i);
  	delay(500);
 	}
}

These are the files regarding all the things involved in this assignment:

Output board files

Output test code

DC driver board files

DC driver test code

Speaker driver board files

Speaker driver test code

Gist & Further development

The problem with output devices is not to integrate and use them, but to fine-tune them. This requires a conjoined knowledge of hardware, software, electronics and common sense that is more easy to obtain with plain experience than extensive planning.

Technically speaking, a board with no output at all is meaningless, so I think it’s better to understand most of them in the best way possible in order to have a sufficient understanding of what to do (and how to do it) in the world of electronics.

Tools and software used