Juan García-Maestro Gil-Casares

FABLAB MADRID CEU


13. Input Devices


Procedure:
0. Assignment
1. Strategy
2. Material I need
3. Designing My Board - Schematic
4. Building My Board - Board Final Design
5. Milling The Board
6. Programming
7. My Final Project's Input Code - Strategy
8. Code Used
9. Problems Accounted
10. Download Files

0. ASSIGNMENT



Measure something: add a sensor to a microcontroller board that you have designed and read it.



LEARNING OUTCOMES



Demonstrate workflows used in circuit board design and fabrication.

Implement and interpret programming protocols.

HAVE YOU...


...described your design and fabrication process using words/images/screenshots
...explained the programming process/es you used and how the microcontroller helped you
...explained problems and how you fixed them.
...included original design files and code.

1. STRATEGY



The goal this week is to continue developing my final project. As the project is to create a lightning device that can be moved without being touched, my idea is to create a new board connected to a sonar.

My idea is to create a program that changes the led's colour depending on the distance read by the sonar.

The reason why I have chosen a sonar and not other devices is because it can read distances. As this device is for my drawing table, at home, I will be moving around my room constantly and I need a device that can be activated at certain distances.

MCU I am going to use:



I will be using a Atmel AtMega 168 with 32 pins. The reason I chose this one is because it has more memory than the ATiny 45 that Neil uses. Plus, in order to have as well a RGB led, I need more pins to connect the led.



My first design was done with a ATiny 44. Later on, thinking more about the functionality of my board, I decided to change to the AtMega.

Your browser does not support this image

Here is the reference with arduino pins:



Your browser does not support this image

What pins I need to connect my ultrasonic device with my mcu?

The ultrasonic sensor needs to be connected to my MCU with two connections: the 'Trigger Pin' and the 'Echo Pin'. The 'Trigger Pin' is connected to pin 'PD5' (or number 5) of my board, and the 'Echo Pin' is connected to 'PD6' (or number 6). On the table below it can be seen the different characteristics of each pin of my board:

Your browser does not support this image

Both pins need to behave in a general way, as only one needs to be activated for a precise moment of time and the other pin listens to the reply. With the moment time, the mcu calculates the distance at which the nearest object is at. A further explanation is done later on in the



The device I will be using is the 'Ultrasonic Ranging Module HC-SR04', from Elec Freaks.

Your browser does not support this image

It has 4 pins: VCC, Trigger, Echo, Ground.

Technical Information: For this sonar, I do not need an extra supply as it works with a 5 volt circuit. It is perfect for me as I need to read distances within a short range (2cm up to 4 m).

Your browser does not support this image

Specifications



-Operating voltage: 5V
-Working current: 16mA.
-Weight: 90g;
-Dimensions: 46 x 20.5 x 19.5 mm (thickness of anti-reverse pin socket included)

Your browser does not support this image

Understanding the Sonar - Company's explanation

As for the ranging principle, it is quite simple to understand: pull up the pin Trig to High thus providing high level signals of at least 10us, so the module starts to detect and measure the distance; if an object is detected, the ECHO pin will be High, and the duration of it being High depends on the distance detected, thus giving the distance calculation formula: Distance = Duration of High ECHO * Speed of sound (340m/s)/2.

2. Material I need




-1MCU AtMega 168
-2 Capacitors 0.1 uF
-2 Capacitors 10 uF
-1 Capacitor 1 uF
-1 Switch/Slide
-1 RGB Led
-1 Resistor 10k
-2 Resistors 1K
-1 Resistor 499 ohms
-1 Jumper (Resistor 0 ohms)
-Jumper
-1 FTDI Male Connector
-1 Resonator 8MHz
-1 Female Connection Pad 1x06 (for the USBTinyISP Programmer)
-1 Female Connection Pad 1x04 (for the sonar)
-1 Sonar HC-SR04 + Cable with male connectors

3. Designing My Board - Schematic



In order to make my board, I had a look to the Fabacademy's archive and based my board on the FabKit's board and Neil's board.

Your browser does not support this image



Your browser does not support this image

Your browser does not support this image

4. Building My Board - Board Final Design



My final board design.



Your browser does not support this image

As everything works with the FTDI Cable supply (5 volts), no additional supply is needed. As done for output devices, I need to change the 'Design Rules' of Eagle Software, to make sure pads on the board are not connected together.
Your browser does not support this image

5. Milling The Board



As in previous situations, I have used the Modela MDX-20 to create my board. Here are my PGNs ready (traces, perimeter, holes):

Your browser does not support this image Your browser does not support this image Your browser does not support this image

Uploading files to Mods:
Your browser does not support this image

CALCULATE



These are the windows that pop up when mods has calculated the milling paths:

Your browser does not support this image

Your browser does not support this image Your browser does not support this image

SEND



When milling the board, I had several problems with mods. Although on the png file the traces are clearly separated, mods did not interpret it in the same way, having some copper without being milled.

Your browser does not support this image

Although it is clearly represented on the image where the mill is going to pass, I did not notice it until it was milled.

Your browser does not support this image

Using a cutter to remove the copper that I did not need:

Your browser does not support this image Your browser does not support this image

Your browser does not support this image

Therefore, I had to make some manual changes + testing there was not a shortcut.

Your browser does not support this image Your browser does not support this image

Continuing building my board

Your browser does not support this image

Finished! Every connection has been checked, well soldered and now I can proceed to program it.

Your browser does not support this image Your browser does not support this image



6. Programming



This design, as the one done before (outputs), instead of soldering a 2x3 pin to the board, I connected a pad 1x06 that connects to the USBFabIsp Programmer. Carefully, I checked which pins correspond to what pins on the FabIsp:

Your browser does not support this image Your browser does not support this image

Your browser does not support this image Your browser does not support this image Your browser does not support this image Your browser does not support this image

Everything Connected! Let's burn the bootloader:

As it happened with outputs, now I have enough memory to burn a bootloader so once installed, I do not need anymore the USBFabIsp Programmer.

Your browser does not support this image Your browser does not support this image Your browser does not support this image

Checking at which port it is connected:

Your browser does not support this image

Adjustments needed:


-Adjustments needed:
-Board: Arduino Pro or Pro Mini
-Processor: Atmega 328 (3.3V, 8 Mhz)
-Port: COM 3
-Programmer: USBTinyIsp
-BURN BOOTLOADER

Your browser does not support this image

ERROR

Error Message when burning the bootloader
"Arduino: 1.8.1 (Windows 10), Board: "Atmel atmega168pb Xplained mini"

avrdude: Expected signature for ATmega168P is 1E 94 0B
Double check chip, or use -F to override this check.
Error while burning bootloader.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences."

For burning the booloader, I forgot that for Arduino to read the ATMega 168 board, I needed to adjust it as an Arduino Pro or Pro Mini Board and not the one I selected.

Your browser does not support this image

Everything was done successfully. Although I had problems with the board, all connections are ok and ready to start the programming.

PROGRAMMING THE BOARD - CHECKING IT WORKS CORRECTLY



To start with, instead of going directly programming the Sonar, I wanted to make sure everything worked OK. Therefore, I took the program I used with the Output Board for checking it was OK and used it with board:

Explaining the 'Test Program':

First I define the different variables for each pin (as they are constant variables, I declare them as such). In my case, the red led is pin A4, the green led is A2 and the blue led is A3.

For the setup, I initialize each pin with the command 'pinMode'. First I start turning on the red led, then use the command 'delay for 1000 milliseconds, turn of the red led and turn on the green led. The same process to end with the blue led, starting the loop all over again.

Your browser does not support this image



PROGRAMMING THE BOARD



As mentioned above, I want to create a program that changes the led's colour depending on the distance read by the sonar. My colleague Daniel Amigo and I have both a sonar device as an input, so I did not doubt to work together or ask him for any help with the programming.



In fact, my program is very similar to his code as we have been working together. The main difference between his program and mine is that I interact as well with the led I have incorporated on the board.

What Does The Program Do?

The goal is to create a program that changes the RGB Led's colour depending on the distance measured. I told the board that, above 10 cm, the RGB Led has to be at {R,G,B};(150, 150, 150). If the distances measured is under those 10cm, then {R,G,B};(50, 75, 241).

How does it work?

For the sonar, I have four pins: a VCC and a GND for power, and a TRIG and ECHO pin. The trigger fires a pulse for 10µseconds and echo reads it. With a quick calculation, I can figure out at what distance the obstacle read by the sonar is at:

Speed of sound: 340 m/s



When I 'digitalWrite (TRIGGERPIN, LOW) to digitalWrite (TRIGGERPIN, HIGH), I create this new impulse. Then I continued with the command digitalWrite (TRIGGERPIN, LOW), so it is activate once.

Visual example:

Your browser does not support this image

Visualisation of Trigger signal and Echo reading signal a few microseconds later:

Your browser does not support this image

(images thanks to mechatronics website)

The difference between when the signal is fired and then is read, is doubled (as the echo pin only reads when the wave comes back) and with that parameter, I multiply it by 0.034 cm/µs and then divided by 2.

Video With My Device



The first video has been taken to show how the sonar measured the distance. The second video is my 5th attempt to change the led's colour, failing. After reviewing the code once and again, I could not manage to achieve the goal of changing the led's colour.





7. My Final Project's Input Code - Strategy



For my final project, I started developing the programming based on my first program. This is the final result:

I have two boards that connect with serial communication. During the programming, I had to face up several problems:


-analyse the four different situations that can take place with the two ultrasonic sensors used.
-make sure the slave board does not saturate from infinite commands sent by the master board.
-the slider's position: the system needs to know where exactly the slider is at, what distance has left to both sides.

Your browser does not support this image

Input Board:



Its responsibility is to analyse if there is an object (my hand) under 10cm. If this is true, then move the slider to one side. Depending on which sonar detects this obstacle, it moves to one side or the other.

The input board is the master board of this system, having the responsibility of:

-send the order to the slave board
-consider all four situations regarding the sonar's readings.
-do not saturate the slave board with orders

Just below, there are two pictures with the most important parts of the input's code. They solve what was written above.

Your browser does not support this image

(code for having an obstacle in sonar1, sending to the slave board number 2)

Sending The Order To The Slave Board

For the board to send the order to that slave board, it uses the command 'mySerial.println(n)'.

Number n can be:

n = 1 - Sends the order to the slave board to not move.
n = 2 - Sends the order to the slave board to move the stepper clockwise, moving the slider to the left.
n = 3 - Sends the order to the slave board to move the stepper counter clockwise, moving the slider to the right.

Analysing The 4 Possible Situations

As you can see on the picture, the first 'if()' is activated depending on the variables 'distance1' and 'distance2'. Each one of this variables have been previously declared assigning them 10. This number 10 refers to the 10cm distance where I will be operating the device. Therefore, if I have my hand under those 10cm, the board will send an order to the salve board. There are four different situations:

-Not reading anything: 'distance1>10' and 'distance2>10', both have measures above 10cm.
-One of the sensors reads an obstacle under those 10cm: 'distance1<10' and 'distance2>10'.
-The other sensor reads an obstacle under those 10cm: 'distance1>10' and 'distance2<10'.
-Both sonars read they have an obstacle under 10 cm: 'distance1<10' and 'distance2<10'.

Depending on each possible situation, the board is going to send one of the number explained before.

How Not To Saturate The Slave Boards With Too Many Commands

Just below, plus the previous image, you have the code I have used:

Your browser does not support this image

(code when both sonars do not have any obstacles and reassign variables 'bucle1', 'bucle2' and 'bucle3'.)

For the board not to send infinite commands, I have used the function 'millis()' to make sure that same command is not repeated all the time. I declare the variable 'interval' (take a look to the code, the image only shows some of it), where I decide how much time it needs to pass so the board can send the same order again.

Initially, 'bucle1', 'bucle2' and 'bucle3' are the variables that make it possible to not send all the time the same command, and the three of them are assigned number 0.

The way it works is very simple: once activated a possible situation, one of the variables changes from 0 to 1. When the loop starts over again, for the same possible situation, there is an initial 'if()' function. This if() function reads: if one of the two other variables are 1, the same command can be sent again, if not, continue with the next part of the code.

Here is the tricky part, I need to wait for the interval to take place so the variables go back to 0 and the same command can be sent again.



8. Code Used



Boarding Test With RGB Led

			const int LED_ROJO = A4; //Pin connected to red led  
const int LED_VERDE = A2; //Pin connected to green led
const int LED_AZUL = A3; //Pin connected to blue led

void setup() {
  // led's initialitation
pinMode(LED_ROJO, OUTPUT);
pinMode(LED_VERDE, OUTPUT);
pinMode(LED_VERDE, OUTPUT);

}

void loop() {
  analogWrite(LED_ROJO, 0); //Red Colour ON
  delay(1000);
  analogWrite(LED_ROJO, 255); //Red Colour OFF
  analogWrite(LED_VERDE, 0); //Green Colour ON
  delay(1000);
  analogWrite(LED_VERDE, 255); //Green Colour OFF
  analogWrite(LED_AZUL, 0); //Blue Colour ON
  delay(1000);
  analogWrite(LED_AZUL, 255); //Blue Colour OFF
  delay(1000);
}
			

MY PROGRAM: MEASURING DISTANCE WITH MY PROGRAM

//declaring rgb led pins
const int LedPinGreen = A2;
const int LedPinRed = A4;
const int LedPinBlue=A3;

//declaring variables sonar pins
const int Echo = 6;
const int Trigger = 5; 


void setup() {
 Serial.begin(9600);
 pinMode(LedPinGreen, OUTPUT);//rgb led
 pinMode(LedPinRed, OUTPUT);
 pinMode(LedPinBlue, OUTPUT);
 
 pinMode(Trigger, OUTPUT); //sonar pins
 pinMode(Echo, INPUT);
 
}
 
void loop() {
 int cm = ping(Trigger, Echo);
 Serial.print("Distancia: ");
 Serial.println(cm);
 delay(1000);

}
 
int ping(int Trigger, int Echo) {
 long duration, distanceCm;
 
 digitalWrite(Trigger, LOW);  //para generar un pulso limpio ponemos a LOW 4us
 delayMicroseconds(4);
 digitalWrite(Trigger, HIGH);  //generamos Trigger (disparo) de 10us
 delayMicroseconds(10);
 digitalWrite(Trigger, LOW);
 
 duration = pulseIn(Echo, HIGH);  //medimos el tiempo entre pulsos, en microsegundos
 
 distanceCm = duration * 10 / 292/ 2;   //convertimos a distancia, en cm
 return distanceCm;
 
 if(distanceCm>'10'){
      analogWrite(LedPinRed,150);// if the distance of the distance sensor is bigger than 10cm, rgb led at (150, 150, 150)
      analogWrite(LedPinGreen,150);
      analogWrite(LedPinBlue, 150);
      }
 
 else{
      analogWrite(LedPinRed,50);// if the distance of the distance sensor is smaller than 10cm, rgb led at (50, 75, 241).
      analogWrite(LedPinGreen,75);
      analogWrite(LedPinBlue, 241);//
}
}      

My Final Project - Input Code



#include <SoftwareSerial.h>
#include <NewPing.h> //including library for ultrasonic sensor
#define TRIGGER_PIN  5 // pin that send a signal
#define ECHO_PIN     6 // pin that receive the signal

#define TRIGGER_PIN2  8 // pin that send a signal
#define ECHO_PIN2     7 // pin that receive the signal
#define MAX_DISTANCE 400 // max distance that the sensor will read

 //initializing both sonars
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // establish the new ping telling which are the pins and the max distance
NewPing sonar2(TRIGGER_PIN2, ECHO_PIN2, MAX_DISTANCE); // establish the new ping telling which are the pins and the max distance

//initializing software serial
SoftwareSerial mySerial(0, 1); //Tx and Rx  pins (respectivamente) - cambiado, originalmente (0,1)


//declaring led variable
int redPin = A4; // Red Led Pin
unsigned long rxTime; //define variable sensor 1
unsigned long rxTime2; //define variable sensor 2
float distance; 
float distance2;
int bucle1=0;
int bucle2=0;
int bucle3=0;
unsigned long previousMillis;
unsigned long currentMillis;
const long interval = 1500;



/*float definition: 
 * is a number that has a decimal point. It is used to approximate analog and continuous values
 * because they have greater resolution than integers. Floating numbers can be as large as
 *3.4028235E+38 and as low as -3.40282335E+38.  
 *32-bit storage (4 bytes of information)
 *6-7 digits of precision
 *
 */
 
void setup() {
  // put your setup code here, to run once:

  //beginning baud rate for serial communication
 mySerial.begin(9600);


//pin activation for sonar1
 pinMode(ECHO_PIN,INPUT);
 pinMode(TRIGGER_PIN,OUTPUT); 


 //pin activation for sonar2
 pinMode(ECHO_PIN2, INPUT);
 pinMode(TRIGGER_PIN2, OUTPUT);

 //pin activation for red led
 pinMode(redPin, OUTPUT);   // sets the pins as output

}

void loop() {

  
  // SONAR 1 READ
  // put your main code here, to run repeatedly:
  digitalWrite(TRIGGER_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER_PIN, LOW);
  rxTime = pulseIn(ECHO_PIN, HIGH); //read the Receive time
  distance = (float)rxTime * 34 / 2000.0; //Converted into a distance ,cm



  // SONAR 2 READ
  digitalWrite(TRIGGER_PIN2, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER_PIN2, LOW);
  rxTime2 = pulseIn(ECHO_PIN2, HIGH); //read the Receive time
  distance2 = (float)rxTime2 * 34 / 2000.0; //Converted into a distance ,cm

/*FOUR POSSIBLE SITUATIONS WHEN READING BOTH SONARS:  1st sonar - left; 2nd sonar - right
 * 1st: 1>10 && 2>10 - neither sonars are activated - no movement expected
 * 2nd: 1<10 && 2>10 - activating left sonar - clockwise motor movement response (moving to the left)
 * 3rd: 1>10 && 2<10 - activating right sonar - counterclockwise motor response (moving to the right)
 * 4th: 1<10 && 2<10 - activating both sonars under 10cm - no movement expected
*/

//motor stepper messages
/*For the slave board:
 * Number 1: do not move or stop moving
 * Number 2: move clockwise, moving the slider to the left
 * Number 3: move counterclockwise, moving the slider to the right
 * */


 
 /*2*/ 
 if ((distance <10) && (distance2>10)) {
    
    if ((bucle1==0) && (bucle2==0) && (bucle3==0)) {
      bucle2=1;
    }
      if ((bucle2==1) || (bucle3==1))
      {
        bucle1=0;
        bucle2=0;
        bucle3=0;
        
        mySerial.println(2);
        bucle1=1; 
        previousMillis = millis();            
       }
    
    }
  
 /*3*/ 
  else if((distance>10) && (distance2<10)) {
     if ((bucle1==0) && (bucle2==0) && (bucle3==0)) {
      bucle3=1;
    }
   
    if ((bucle1==1) || (bucle3==1)){
        bucle2=0;
        bucle1=0;
        bucle3=0;
        
        mySerial.println(3);
        bucle2=1;
        previousMillis=millis();
    }
    
    
  }

/*ambas*/
  else if ((distance <10) && (distance<10)) {
     if ((bucle1==0) && (bucle2==0) && (bucle3==0)) {
      bucle1=1;
    }
    
        if((bucle2==1) || (bucle3==1)) 
        {
          bucle3=0;
          bucle1=0;
          bucle2=0;
        
          mySerial.println(1);
          bucle3=1;
          previousMillis=millis();
          }
    
  } 
    
   else if((distance > 10) && (distance2 >10)) {
        currentMillis = millis();
  
       if (currentMillis - previousMillis >= interval) {
      bucle1=0;
      bucle2=0;
      bucle3=0;
      
    }
 
}
}




9. Problems Accounted



Milling The Board



Your browser does not support this image

As mentioned above, I solved the problem of not milling correctly by with a cutter cutting those parts that were not meant to be there. I successfully did that, making sure everything was connected together.

Your browser does not support this image Your browser does not support this image

Forgetting To Connect My Programmer To Burn The Bootloader



A common mistake that sometimes I forget.

Your browser does not support this image




Failing with the 1st Program

Failing at what my initial program (changing the RGB Led colour depending on the distance measured). It seems as if the code is correct. Further investigation is needed here. The reason why I did not continue with it is because I started developing my final project.

10. Download Files




Arduino Files