Week 10 - Input Device (Depth Measurement)


Posted by Jordan Kennedy on November 21, 2017

This week we had to make an input device.

The input device I intend to make will be apart of my final project and will be updated accordingly.

To prepare I initially copied a touch pad board.

sensor

It didn’t program correctly which means I need to revist it.

However, for my final project I want to discretely be able to measure the water depth as I have shown in the drawning below.

This means I will need more leads and to redraw my board with more inputs to get a usable resolution.

senosridea

I am hoping that the touch pad configuration will be sensitive to water.

Revisiting the Touch Pad (12/05)

I am modifying the touch pad design to serve as a water depth sensor for my tank. My intent for this device is to use water depth as an on/off switch. As water contacts the pad, it completes the circuit. In order to achieve this I need to design to the resitivity of water. The resistivity of water is approximately 200 ohm.m.

Resistance and resistivity are related through the following equation.

resistivity

Drawn below is a simplified version of how each of the touchpads acts as a switch.

voltagedivide

Shown below is my design. It supports 12 inputs. I’m intending to use 10 of them. It can be thought of as 10 on/off switches.

depthsensor

I even made the board, but I never programmed it. Neil suggested that instead of using resistance, I use capacitance.

depthsensorboard

So then I modified the Hello World board to work as my initial try at depth sensing.

Capacitance Depth Sensing (12/13)

First, I looked up how Capacitive Depth Sensors Work.

CapSense

CapBoard

I also had to make my capacitive nodes. For future use I will need to make something more robost. However, for proof of concept, I took two copper sheets, connect a wire to each, and covered with clear packaging tape as an insulator.

My capacitive sensors are below.

CapSense

Below is the Code:

//
//
// hello.ftdi.44.echo.c
//
// 115200 baud FTDI character echo, with flash string
//
// set lfuse to 0x5E for 20 MHz xtal
//
// Neil Gershenfeld (modified by JK)
// 12/8/10
//
// (c) Massachusetts Institute of Technology 2010
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose. Copyright is
// retained and must be preserved. The work is provided
// as is; no warranty is provided, and users accept all
// liability.
//

#include <avr/io.h>

#include <util/delay.h>

#include <avr/pgmspace.h>


#define output(directions,pin) (directions |= pin) // set port direction for output

#define set(port,pin) (port |= pin) // set port pin

#define clear(port,pin) (port &= (~pin)) // clear port pin

#define pin_test(pins,pin) (pins & pin) // test for port pin

#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set

#define bit_delay_time 8.5 // bit delay for 115200 with overhead

#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay

#define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay

#define charge_delay_1() _delay_us(1) // charge delay 1

#define charge_delay_2() _delay_us(10) // charge delay 2

#define charge_delay_3() _delay_us(100) // charge delay 3

#define settle_delay() _delay_us(100) // settle delay

#define char_delay() _delay_ms(10) // char delay


#define serial_port PORTA

#define serial_direction DDRA

#define serial_pins PINA

#define serial_pin_in (1 << PA0)

#define serial_pin_out (1 << PA1)


#define charge_port PORTB

#define charge_direction DDRB

#define charge_pin (1 << PB2)


#define ref (0 << REFS1) | (0 << REFS0) // reference voltage


#define sense0 (1 << MUX2) | (1 << MUX1) | (1 << MUX0) // PA7


#define down_threshold 700

#define up_threshold 750


#define max_buffer 25


#define printDebug 0


void get_char(volatile unsigned char *pins, unsigned char pin, char *rxbyte) {
  //
  // read character into rxbyte on pins pin
  //    assumes line driver (inverts bits)
  //
  *rxbyte = 0;
  while (pin_test(*pins, pin))
    //
    // wait for start bit
    //
    ;
  //
  // delay to middle of first data bit
  //
  half_bit_delay();
  bit_delay();
  //
  // unrolled loop to read data bits
  //
  if pin_test(*pins, pin)
    *rxbyte |= (1 << 0);
  else
    *rxbyte |= (0 << 0);
  bit_delay();
  if pin_test(*pins, pin)
    *rxbyte |= (1 << 1);
  else
    *rxbyte |= (0 << 1);
  bit_delay();
  if pin_test(*pins, pin)
    *rxbyte |= (1 << 2);
  else
    *rxbyte |= (0 << 2);
  bit_delay();
  if pin_test(*pins, pin)
    *rxbyte |= (1 << 3);
  else
    *rxbyte |= (0 << 3);
  bit_delay();
  if pin_test(*pins, pin)
    *rxbyte |= (1 << 4);
  else
    *rxbyte |= (0 << 4);
  bit_delay();
  if pin_test(*pins, pin)
    *rxbyte |= (1 << 5);
  else
    *rxbyte |= (0 << 5);
  bit_delay();
  if pin_test(*pins, pin)
    *rxbyte |= (1 << 6);
  else
    *rxbyte |= (0 << 6);
  bit_delay();
  if pin_test(*pins, pin)
    *rxbyte |= (1 << 7);
  else
    *rxbyte |= (0 << 7);
  //
  // wait for stop bit
  //
  bit_delay();
  half_bit_delay();
}

void put_char(volatile unsigned char *port, unsigned char pin, char txchar) {
  //
  // send character in txchar on port pin
  //    assumes line driver (inverts bits)
  //
  // start bit
  //
  clear(*port, pin);
  bit_delay();
  //
  // unrolled loop to write data bits
  //
  if bit_test(txchar, 0)
    set(*port, pin);
  else
    clear(*port, pin);
  bit_delay();
  if bit_test(txchar, 1)
    set(*port, pin);
  else
    clear(*port, pin);
  bit_delay();
  if bit_test(txchar, 2)
    set(*port, pin);
  else
    clear(*port, pin);
  bit_delay();
  if bit_test(txchar, 3)
    set(*port, pin);
  else
    clear(*port, pin);
  bit_delay();
  if bit_test(txchar, 4)
    set(*port, pin);
  else
    clear(*port, pin);
  bit_delay();
  if bit_test(txchar, 5)
    set(*port, pin);
  else
    clear(*port, pin);
  bit_delay();
  if bit_test(txchar, 6)
    set(*port, pin);
  else
    clear(*port, pin);
  bit_delay();
  if bit_test(txchar, 7)
    set(*port, pin);
  else
    clear(*port, pin);
  bit_delay();
  //
  // stop bit
  //
  set(*port, pin);
  bit_delay();
  //
  // char delay
  //
  bit_delay();
}

void put_string(volatile unsigned char *port, unsigned char pin, char *str) {
  //
  // print a null-terminated string
  //
  static int index;
  index = 0;
  do {
    put_char(port, pin, str[index]);
    ++index;
  } while (str[index] != 0);
}

int check_pin(unsigned char pin) {
  unsigned char up_lo,up_hi,down_lo,down_hi;
  int up_value, down_value;
  float value;
  int val_array[100];
  value = 100;
  char numStr[8];
  //
  // set the A/D pin
  //
  ADMUX = ref | pin;
  
  //
  // settle, charge, and wait 1
  //
  settle_delay();
  set(charge_port, charge_pin);
  //
  // initiate conversion
  //
  for(int i = 0; i < 100; i++)
  {
    ADCSRA |= (1 << ADSC);
    //
    // wait for completion
    //
    while (ADCSRA & (1 << ADSC))
      ;
    //
    // save result
    //
    up_lo = ADCL;
    up_hi = ADCH;
    val_array[i] = 256 * up_hi + up_lo;
  }
  //
  // settle, discharge, and wait 1
  //
  settle_delay();
  clear(charge_port, charge_pin);
  for(int i = 0; i < 100; i++)
  {
    if(val_array[i] < 50)
    {
      value = i+1;
      if (printDebug)
      {
        put_string(&serial_port, serial_pin_out, "ADC Sample: ");
        itoa(i+1,numStr,10);
        put_string(&serial_port, serial_pin_out, numStr);
        put_char(&serial_port, serial_pin_out, ' ');
        char_delay();
      }
      break;
    }
  }
  if (printDebug)
  {
    put_char(&serial_port, serial_pin_out, '\r');
    char_delay();
    put_char(&serial_port, serial_pin_out, '\n');
    char_delay();
  }

  //
  // process result
  //
  /*
  up_value = 256 * up_hi + up_lo;
  //down_value = 256 * down_hi + down_lo;
  //value = (up_value + (1023 - down_value)) / 2;
  value = up_value;
 */
  //itoa(up_value,numStr,10);
  //put_string(&serial_port, serial_pin_out, "Up Value: ");
  //put_string(&serial_port, serial_pin_out, numStr);
  //itoa(down_value,numStr,10);
  //put_string(&serial_port, serial_pin_out, ", Down Value: ");
  //put_string(&serial_port, serial_pin_out, numStr);
  //put_char(&serial_port, serial_pin_out, '\n');
  //char_delay();
  
  return value;
}

void sense_pin(unsigned char pin, int *oldValue, char labelChar) {
  int value = 0;
  int numLoops = 10;
  for(int i = 0; i<numLoops; i++)
  {
    value += check_pin(pin);
  }

  int decay_ADCMeasCycles = value/numLoops;
  
  char numStr[5];
  itoa(decay_ADCMeasCycles,numStr,10);
  put_string(&serial_port, serial_pin_out, "ADC Measure Cycles: ");
  put_string(&serial_port, serial_pin_out, numStr);
  put_string(&serial_port, serial_pin_out, "\r\n");
}

int main(void) {
  //
  // main
  //
  static char chr;
  static char buffer[max_buffer] = {0};
  static int index;
  static int meas7;
  char numStr[5];
  meas7 = 0;
  //
  // set clock divider to /1
  //
  CLKPR = (1 << CLKPCE);
  CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
  //
  // initialize output pins
  //
  set(serial_port, serial_pin_out);
  output(serial_direction, serial_pin_out);
  clear(charge_port, charge_pin);
  output(charge_direction, charge_pin);

  //
  // init A/D
  //
  ADMUX = ref; // Vcc ref
  ADCSRA = (1 << ADEN) // enable
    | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128
  ADCSRB = (0 << ADLAR); // right adjust
  
  //
  // main loop
  //
  index = 0;
  while (1) {
    //get_char(&serial_pins, serial_pin_in, &chr);
    //put_string(&serial_port, serial_pin_out, "Loop");
    sense_pin(sense0, &meas7, '7');
    charge_delay_3();
    //put_char(&serial_port, serial_pin_out, 10); // new line
  }
}