Multi-touch force & position sensing with Arduino
Now that the hardware's connected, it's time to write some code.
To read a single intersection, or "cell", of the MatrixArray, we need to perform the following sequence:
Simple enough, so from here, we will write a scan pattern to efficiently drive and read each cell of the Matrix. Recalling that we're calling shift register drive pins "rows" and multiplexed read pins "columns" in this example, we'll enable each column in order, and while each column is active, we'll drive each row high and take a reading.
The code example below implements a scan pattern, and continuously dumps output to a serial terminal.
⬇ Download MatrixArray.zip (Arduino Project)
/**********************************************************************************************************
* Project: MatrixArray.ino
* By: Chris Wittmier @ Sensitronics LLC
* LastRev: 09/09/2015
* Description: FSR MatrixArray Demonstration of Sensitronics' 16x10 element resistive ThruMode. Scanning
* electronics consist of 2 HCT595 shift registers, and 2 4051 multiplexers connected to Arduino Uno.
**********************************************************************************************************/
#define BAUD_RATE 115200
#define ROW_COUNT 10
#define COLUMN_COUNT 16
#define PIN_ADC_INPUT A0
#define PIN_SHIFT_REGISTER_DATA 2
#define PIN_SHIFT_REGISTER_CLOCK 3
#define PIN_MUX_CHANNEL_0 4
#define PIN_MUX_CHANNEL_1 5
#define PIN_MUX_CHANNEL_2 6
#define PIN_MUX_INHIBIT_0 7
#define PIN_MUX_INHIBIT_1 8
#define ROWS_PER_MUX 8
#define MUX_COUNT 2
#define CHANNEL_PINS_PER_MUX 3
int current_enabled_mux = MUX_COUNT - 1;
void setup()
{
Serial.begin(BAUD_RATE);
pinMode(PIN_ADC_INPUT, INPUT);
pinMode(PIN_SHIFT_REGISTER_DATA, OUTPUT);
pinMode(PIN_SHIFT_REGISTER_CLOCK, OUTPUT);
pinMode(PIN_MUX_CHANNEL_0, OUTPUT);
pinMode(PIN_MUX_CHANNEL_1, OUTPUT);
pinMode(PIN_MUX_CHANNEL_2, OUTPUT);
pinMode(PIN_MUX_INHIBIT_0, OUTPUT);
pinMode(PIN_MUX_INHIBIT_1, OUTPUT);
}
void loop()
{
for(int i = 0; i < ROW_COUNT; i ++)
{
setRow(i);
shiftColumn(true);
shiftColumn(false);
for(int j = 0; j < COLUMN_COUNT; j ++)
{
int raw_reading = analogRead(PIN_ADC_INPUT);
byte send_reading = (byte) (lowByte(raw_reading >> 2));
shiftColumn(false);
printFixed(send_reading);
Serial.print(" ");
}
Serial.println();
}
Serial.println();
delay(200);
}
void setRow(int row_number)
{
if((row_number % ROWS_PER_MUX) == 0)
{
digitalWrite(PIN_MUX_INHIBIT_0 + current_enabled_mux, HIGH);
current_enabled_mux ++;
if(current_enabled_mux >= MUX_COUNT) { current_enabled_mux = 0; }
digitalWrite(PIN_MUX_INHIBIT_0 + current_enabled_mux, LOW);
}
for(int i = 0; i < CHANNEL_PINS_PER_MUX; i ++)
{
if(bitRead(row_number, i)) { digitalWrite(PIN_MUX_CHANNEL_0 + i, HIGH); }
else { digitalWrite(PIN_MUX_CHANNEL_0 + i, LOW); }
}
}
void shiftColumn(boolean is_first)
{
if(is_first) { digitalWrite(PIN_SHIFT_REGISTER_DATA, HIGH); }
digitalWrite(PIN_SHIFT_REGISTER_CLOCK, HIGH);
digitalWrite(PIN_SHIFT_REGISTER_CLOCK, LOW);
if(is_first) { digitalWrite(PIN_SHIFT_REGISTER_DATA, LOW); }
}
void printFixed(byte value)
{
if(value < 10) { Serial.print(" "); }
else if(value < 100) { Serial.print(" "); }
Serial.print(value);
}