Skip to content

12. Input devices

This week’s assignment was to measure something: add a sensor to a microcontroller board that I have designed and read it.

Group assigment

This week group assigment was probe an input device(s)’s analog levels and digital signals. We tested Sharp GP2Y0A21YK0F(analog sensor) and HC-SR04 Ultrasonic Sensor(digital sensor). We wrote code with NewPing.h library and without it. What was interesting for me that sensor don’t work with fabric materials. Then we found out that sesnor needed a pretty solid object to bounce sound for this walls are good but cloth absorbs the sound wave and the echo never bounces back. Here are a codes we used. First without library.

const int trigPin = 9;
const int echoPin = 10;

float duration, distance;

void setup() {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);
  distance = (duration*.0343)/2;
  Serial.print("Distance: ");
  Serial.println(distance);
  delay(100);
}

With NewPing.h library.

#include <NewPing.h>
#define TRIGGER_PIN 12 // Arduino pin connected to the sensor's trigger pin
#define ECHO_PIN 11    // Arduino pin connected to the sensor's echo pin
#define MAX_DISTANCE 200 // Maximum distance to measure (in centimeters)

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

void setup() {
    Serial.begin(9600);
}

void loop() {
    delay(50); // Wait for sensor stability
    unsigned int distance = sonar.ping_cm();
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.println(" cm");
}

We also tested sensor with oscilloscope. Here is a result.

When the distance between the sensor and the detected object is smaller wave in oscilloscope become smaller.

After that we used Sharp GP2Y0A21YK0F sensor. The Sharp GP2Y0A21YK0F is an infrared (IR) distance sensor that uses infrared light to measure distances. The sensor emits an infrared beam towards an object. When the beam reflects off the object, it reaches a light detector (Position Sensing Device or PSD). The position of the reflected beam on the PSD changes as the object’s position changes. The sensor’s built-in signal processing circuit calculates the distance based on the position of the optical spot on the PSD. It outputs an analog signal that corresponds to the object’s distance in front of the sensor. First we wired the sensor and write code that gave as the sensor, and start manualy measured it.

#define IR_SENSOR_PIN A0

void setup() {
    Serial.begin(9600);
}

void loop() {
    int sensorValue = analogRead(IR_SENSOR_PIN);
    Serial.println(sensorValue);
}

After that we wrote result in Excel made table that had two columns analog values and distance that we measured and made chart with excel.

The relationship between the sensor’s analog output voltage and the distance is often nonlinear as we can see in our example. In the case of the GP2Y0A21YK0F, this relationship approximated by an exponential function. In code we foret minus sign but we corrected it and it worked. In our case function was 145712x^-1.05 We wrote code using our result.

int irsensor=A0;
int sensorValue;
void setup(){
  pinMode(irSenor,INPUT);
  Serial.begin(9600);
}
void loop(){
  sensorValue=analogRead(irSensor);
  float distance= 145712*pow(sensorValue,-1.05);
  Serial.println(sensorValue);
  delay(500);
}

It worked but not very accurate.Maybe because of ambient light, and noise or we needed to do more measurments.

After that we found code that worked more accurate.

const int sensorPin = A0;
const long referenceMv = 5000;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  //reading the voltage
  int val = analogRead(sensorPin);
  int mV = (val * referenceMv) / 1023;
  int cm = getDistance(mV);


  //display values on the screen
  Serial.print(mV);
  Serial.print(",");
  Serial.println(cm);

  delay(1000);
}

//interpolation of distance at 250mV intervals
const int TABLE_ENTRIES = 12;
const int INTERVAL  = 250;
static int distance[TABLE_ENTRIES] = {150,140,130,100,60,50,40,35,30,25,20,15};

int getDistance(int mV) {
  if (mV > INTERVAL * TABLE_ENTRIES - 1)      return distance[TABLE_ENTRIES - 1];
  else {
    int index = mV / INTERVAL;
    float frac = (mV % 250) / (float)INTERVAL;
    return distance[index] - ((distance[index] - distance[index + 1]) * frac);
  }
}

Individual assigment

This week I decided use input device that I needed in my final project the filament runout sensor. I did research and found some ways that I can made it. 1. Filament Runout Encoder 2. Filament Sensorwith End switch The common way that I found was with end switch. I wanted to test sensor that worked with capacitive touch. Maxime sent me useful links to understand how it works. Capacitive Sensing with Chris Taylor tutorial Capacitive sensor, Theory, application and design Capacitive Sensing Library

After that I read Adrian’s documentation and it helped me a lot. Adrinan’s documentation I decided for testing made Adrian’s Step Response board and tested it to understand it would work with filament or not.

After that I connected it with my board.

When I wrote the code and uploaded to my board but in Serial monitor didn’t printed any result.

I also tried to upload other code with CapasitiveSensor.h library but it didn’t work too because I used UPDI Serial programming. That’s why I decided to add LCD screen for monitoring results. In my board I used SCL and SDA pins to connect SMD led and button and thats help me find the solution ow in software level I can make other digital pins to SDA and SCL. I used SoftwareWire.h and hd44780.h libraries. I found this solution in Arduino Forum. Arduino forum solution After that I rewrite code.

#include <SoftwareWire.h>
const int sda = 0, scl = 1;
SoftwareWire Wire(sda, scl);
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;   // declare lcd object and let it auto-configure everything.
long result;          //variable for the result of the tx_rx measurement.
int analog_pin = 10;  //  PA5 of the ATtiny1614
int tx_pin = 9;
void setup() {
  int istatus;

  istatus = lcd.begin(16, 2);
  if (istatus) {
    // LCD initalization failed.
    // handle it anyway you want
    if (istatus < 0)
      istatus = -istatus;
    lcd.fatalError(istatus);  // blinks error if LED_BUILTIN is defined
  }
  pinMode(tx_pin, OUTPUT);  //Pin 2 provides the voltage step
  Serial.begin(9600);
}
long tx_rx() {  //Function to execute rx_tx algorithm and return a value
                //that depends on coupling of two electrodes.
                //Value returned is a long integer.
  int read_high;
  int read_low;
  int diff;
  long int sum;
  int N_samples = 100;  //Number of samples to take.  Larger number slows it down, but reduces scatter.

  sum = 0;

  for (int i = 0; i < N_samples; i++) {
    digitalWrite(tx_pin, HIGH);          //Step the voltage high on conductor 1.
    read_high = analogRead(analog_pin);  //Measure response of conductor 2.
    delayMicroseconds(100);              //Delay to reach steady state.
    digitalWrite(tx_pin, LOW);           //Step the voltage to zero on conductor 1.
    read_low = analogRead(analog_pin);   //Measure response of conductor 2.
    diff = read_high - read_low;         //desired answer is the difference between high and low.
    sum += diff;                         //Sums up N_samples of these measurements.
  }
  return sum;
}  //End of tx_rx function.


void loop() {

  result = tx_rx();
  result = map(result, 8000, 11000, 0, 1023);  //I recommend mapping the values of the two copper plates, it will depend on their size
  lcd.print(result);
  delay(400);
  lcd.clear();
}

Here are the first test results. At first I just tried understand how they work and didn’t consider the distance bettwin two plates also the size of plates. Here is the result when the plates far from each other and I din’t touch them.

Here when I touch the plate that I connect Tx pin.

And here when I touched two plates at the same time.

After first test I realized that I can change the values of the mapping for not getting the result with minus sign. result = map(result, 3500, 8000, 0, 1023);

It helped but again the values that I got changed their range very fast. I tried to use 2 different size of copper plate understand how it change the result.

Becuase the difference of numbers stayed a lot I tried motified a code a little bit.

#include <SoftwareWire.h>
const int sda = 0, scl = 1;
SoftwareWire Wire(sda, scl);
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;   // declare lcd object and let it auto-configure everything.
long result;          //variable for the result of the tx_rx measurement.
int analog_pin = 10;  //  PA5 of the ATtiny1614
int tx_pin = 9;
void setup() {
  int istatus;

  istatus = lcd.begin(16, 2);
  if (istatus) {
    // LCD initalization failed.
    // handle it anyway you want
    if (istatus < 0)
      istatus = -istatus;
    lcd.fatalError(istatus);  // blinks error if LED_BUILTIN is defined
  }
  pinMode(tx_pin, OUTPUT);  //Pin 2 provides the voltage step
  Serial.begin(9600);
}
long tx_rx() {  //Function to execute rx_tx algorithm and return a value
                //that depends on coupling of two electrodes.
                //Value returned is a long integer.
  int read_high;
  int read_low;
  int diff;
    digitalWrite(tx_pin, HIGH);          //Step the voltage high on conductor 1.
    read_high = analogRead(analog_pin);  //Measure response of conductor 2.
    delayMicroseconds(100);              //Delay to reach steady state.
    digitalWrite(tx_pin, LOW);           //Step the voltage to zero on conductor 1.
    read_low = analogRead(analog_pin);   //Measure response of conductor 2.
    diff = read_high - read_low;         //desired answer is the difference between high and low.
  return diff;
}  


void loop() {

  result = tx_rx();
  lcd.print(result);
  delay(400);
  lcd.clear();
}

I removed for loop and test it with a single sample.

The values that I got again changed fast. After tat again I modified a code and added a code that count average of result that got from 100 samples.

#include <SoftwareWire.h> 
const int sda=0, scl=1;
SoftwareWire Wire(sda,scl);
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd; // declare lcd object and let it auto-configure everything.
long result;   //variable for the result of the tx_rx measurement.
int analog_pin =10; //  PA5 of the ATtiny1614
int tx_pin =9 ;
void setup()
{
int istatus;

  istatus = lcd.begin(16,2);
  if(istatus)
  {
 // LCD initalization failed.
 // handle it anyway you want
 if(istatus < 0)
 istatus = -istatus;
 lcd.fatalError(istatus); // blinks error if LED_BUILTIN is defined
  }
  pinMode(tx_pin,OUTPUT);      //Pin 2 provides the voltage step
Serial.begin(9600);

}
long tx_rx(){         //Function to execute rx_tx algorithm and return a value
                      //that depends on coupling of two electrodes.
                      //Value returned is a long integer.
  int read_high;
  int read_low;
  int diff;
  long int sum;
  int N_samples = 100;    //Number of samples to take.  Larger number slows it down, but reduces scatter.

  sum = 0;

  for (int i = 0; i < N_samples; i++){
   digitalWrite(tx_pin,HIGH);              //Step the voltage high on conductor 1.
   read_high = analogRead(analog_pin);        //Measure response of conductor 2.
   delayMicroseconds(100);            //Delay to reach steady state.
   digitalWrite(tx_pin,LOW);               //Step the voltage to zero on conductor 1.
   read_low = analogRead(analog_pin);         //Measure response of conductor 2.
   diff = read_high - read_low;       //desired answer is the difference between high and low.
 sum += diff;                       //Sums up N_samples of these measurements.
 }
  return sum/N_samples;
}                         //End of tx_rx function.


void loop() {

result = tx_rx();
//result = map(result,3500,8000, 0, 1023);  //I recommend mapping the values of the two copper plates, it will depend on their size
lcd.print(result);
delay(400);
lcd.clear();
}

This time I got more accurate result.

As I want to make filament runout sensor sensor for my final project I started to test it wit filament. At fitst I just inside 2 coppers but it was not good idea because I didn’t manage to fix it properly. After that I tested it pen case I sticked to plates outside of case.

The difference between values was 1. But I tink it aren’t enough for making sensor with step sensor. I also cut a little bit big 2 plates and put it outside of little plastic box for testing.

At first I thought it would work but after few seconds the result in te screen changed the same value that was when the was empty.

I also tried with different sizes of plates and with different distance between them Areg and Maxime helped me a lot giving ideas of different ways of testing and tested it with me. All version didn’t work well. Rudolf suggest use Universal treadmill magnetic sensor (1A05 Sharp) first I tested it with oscilloscope. After that I wrote code for testing it and it’s worked.

#include <SoftwareWire.h>
const int sda = 0, scl = 1;
SoftwareWire Wire(sda, scl);
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;
void setup() {
  pinMode(8, INPUT);
  Serial.begin(9600);
  int istatus;

  istatus = lcd.begin(16, 2);
  if (istatus) {
    // LCD initalization failed.
    // handle it anyway you want
    if (istatus < 0)
      istatus = -istatus;
    lcd.fatalError(istatus);  // blinks error if LED_BUILTIN is defined
  }
}
int counter = 0;
void loop() {
  int sensorVal = digitalRead(8);
  if (sensorVal != 0) {
    counter++;
    lcd.clear();
    lcd.print(counter);
    delay(500);

  }
}