skin <-> substrate <-> earth

Overlaying the measurement of skin impedance/resistance with earth impedance by using the fingers as measurement probes within context of geophysical earth resistance measurement. Electrodes are replaced by fingers digging into the earth. A measurement of parallel impedance of earth and skin is obtained. Plotting of measurements on ad-hoc hand-drawn maps.

code:

sse.c
/* with Nokia 3310 as output */
 
/* - notes:
   -  5 pins for NOKIA
   -  sce, reset, dc, sdin,sclk
   -  4 pins for bridge (generate/test negative supply for op-amp)
*/
 
#define F_CPU 12000000UL  // 12 MHz
 
#include <avr/io.h>
#include <stdio.h>
#include <inttypes.h>
#include <avr/delay.h>
#include <avr/iom8.h>
#include <avr/interrupt.h>
 
#define byte unsigned char
#define LOW 0
#define HIGH 1
#define LCD_CMD   0
#define LCD_C     LOW
#define LCD_D     HIGH
#define LCD_X     84
#define LCD_Y     48
#define sbi(var, mask)   ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask)   ((var) &= (uint8_t)~(1 << mask))
 
void LcdWrite(byte dc, byte data);
 
static const byte ASCII[][5] =
  {
    {0x00, 0x00, 0x00, 0x00, 0x00} // 20  
        ,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
    ,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
    ,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
    ,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
    ,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
    ,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
    ,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
    ,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
    ,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
    ,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
    ,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
    ,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
    ,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
    ,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
    ,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
    ,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
    ,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
    ,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
    ,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
    ,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
    ,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
    ,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
    ,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
    ,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
    ,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
    ,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
    ,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
    ,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
    ,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
    ,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
    ,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
        ,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
    ,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
    ,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
    ,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
    ,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
    ,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
    ,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
    ,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
    ,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
    ,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
    ,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
    ,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
    ,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
    ,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
    ,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
    ,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
    ,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
    ,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
    ,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
    ,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
    ,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
    ,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
    ,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
    ,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
    ,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
    ,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
    ,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
    ,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
    ,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c ¥
    ,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
    ,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
        ,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
    ,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
    ,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
    ,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
    ,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
    ,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
    ,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
    ,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
    ,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
    ,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
    ,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
    ,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j 
    ,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
    ,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
    ,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
    ,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
    ,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
    ,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
    ,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
    ,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
    ,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
    ,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
    ,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
    ,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
    ,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
    ,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
    ,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
    ,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
    ,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
    ,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
    ,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
    ,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ←
    ,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f →
  };
 
void delay(int ms){
  while(ms){
    _delay_ms(0.96);
    ms--;
  }
}
 
void adc_init(){
  DDRC=0x00; PORTC=0x00;
  unsigned char channel = 0;
  ADMUX=(channel & 0x0f);
  // ADCSRA: ADC Control and Status Register
  // ADPS2..ADPS0: ADC frequency Prescaler Select Bits
  // ADEN: Analog Digital Converter Enable, set this before setting ADSC
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescalar to 128
  ADMUX |= (1 << REFS0); // Set ADC reference to AVCC
  //  ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading
  ADCSRA |= (1 << ADEN);  // Enable ADC
  //  ADCSRA |= (1 << ADSC);  // Start A2D Conversions 
}
 
unsigned int adcread(short channel){
  unsigned int ADresult;
 
  ADMUX = (ADMUX & (unsigned int) 0xf0) | (channel & (unsigned int) 0x0f);
  _delay_ms(10);
  ADCSRA |= (1 << ADSC);  // Start A2D Conversions 
  while (bit_is_set(ADCSRA, ADSC));
  ADresult = ADCL;
  ADresult |= ((int)ADCH) << 8;
  return(ADresult);
}
 
 
void LcdCharacter(char character)
{
  LcdWrite(LCD_D, 0x00);
  for (int index = 0; index < 5; index++)
    {
      LcdWrite(LCD_D, ASCII[character - 0x20][index]);
    }
  LcdWrite(LCD_D, 0x00);
}
 
void LcdClear(void)
{
  for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
    {
      LcdWrite(LCD_D, 0x00);
    }
}
 
void LcdString(char *characters)
{
  while (*characters)
    {
      LcdCharacter(*characters++);
    }
}
 
void LcdWrite(byte dc, byte data)
{
  int x;
  if (dc==LOW) cbi(PORTD,5);
  else sbi(PORTD,5);
  cbi(PORTD, 0);
  //  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
  for (x=7;x>=0;x--){
    //    MSB first
    if (((data>>x)&1)==0) cbi(PORTD,6);
    else sbi(PORTD,6);
    sbi(PORTD,7);     // toggle pin 7 SCLK
    cbi(PORTD,7);
  }
 
  sbi(PORTD, 0);
}
 
void LcdInitialise(void)
{
 
  DDRD=0xE3; // SCE as d0, RESET as d1, DC as d5, SDIN as d6, SCLK as d7 - all outs
  DDRC=0x0E;// TODO add pc1/2/3 as charge pump
  cbi(PORTD, 1);
  sbi(PORTD, 1);
 
  LcdWrite( LCD_CMD, 0x21 );  // LCD Extended Commands.
  LcdWrite( LCD_CMD, 0xBf );  // Set LCD Vop (Contrast). //B1
  LcdWrite( LCD_CMD, 0x04 );  // Set Temp coefficent. //0x04
  LcdWrite( LCD_CMD, 0x14 );  // LCD bias mode 1:48. //0x13
  LcdWrite( LCD_CMD, 0x0C );  // LCD in normal mode. 0x0d for inverse
 
  LcdWrite(LCD_C, 0x20);
  LcdWrite(LCD_C, 0x0C);
}
 
int main(){
 
  int x,y,z,adc,lenny=0,index,count=0;
  unsigned char mybuffer[16]; 
  // init
 
  adc_init();
  LcdInitialise();
  LcdClear();
 
  // pins for 2 bridges +- = PB0-PB3
 
  DDRB=0x0F;
 
  /* port rest of soil testing - flip/sample/display */
 
  while(1){
 
 
    sbi(PORTB,1); cbi(PORTB,0);
    delay(36); // 137 hz
 
    x = adcread(0);    
 
    cbi(PORTB,1); sbi(PORTB,0);
    delay(36);
    y = adcread(0);    
 
    if (x>y) adc+=x-y;
    if (x<y) adc+=y-x;
    count++;
 
    //    LcdString("abcdefghijklmnopqrstuvwxyz");
 
        if (count>32){
      z=adc/32;
 
 
      for (index = 0; index < 504-(lenny*7); index++) 
    {
      LcdWrite(LCD_D, 0x00);
    }
 
      lenny=sprintf(mybuffer,"xx: %d",x);
 
      LcdString(mybuffer);
      //	    LcdString("Hello World!");
      adc=0;
      count=0; 
      // pause also for one second
      delay(1000);
      }	 
    }
  }

LCD code from: http://www.arduino.cc/playground/Code/PCD8544