Code adaptation for reading a pressure sensor matrix

Hello everybody!

First of all, I would like to thank everyone that is taking the time to read this!

I am in the middle of my thesis project from university, which consists on adapting and optimating obstetrical forceps. On the surface of the forceps a pressure sensor matrix mat will be attached, to be able to get a pressure feedback from the pressure the doctor is applying on the babys head. (very very much summarized).
For the data acquisition and data processing I have found a tutorial from the company Sensitronics. They explain and give the code to read a matrix sensor of 16x10 with an Arduino Uno.
My sensor consists of 7x5 electrodes instead of 16x10 and I am trying to adapt the code that I have to my sensor.
Could anybody help me out? I am a little bit lost in the subject.
On the Zip folder attached, I have provided the Circuit and the Sensor layout, for both my sensor and the one I have as exaple (so you guys can see easier for yourselfs what the situation is), as well as the Arduino Code that I am trying to adapt.

My circuit consist of one less multiplexer and one less shiftregister, as the one I have as an example. And on the code I cant really recognize where the programming for these components is.

I would be so thankful if someobody could help me out with this.

Have a very nice day :slight_smile:

Project.zip (796 KB)

If you want help, you had better learn how to incorporate inline code with code tags into your post. I will not be bothered to download and unzip a file.

Somewhere in the code should be declaration of a 16 x 10 matrix. Change it to 7 x 5.

In general you have to adjust ROW_COUNT, COLUMN_COUNT and MUX_COUNT. The code can be simplified further, but for now this should be sufficient.

Eventually you can use a 3 bit decoder instead of the shift register, but that depends on whether the outputs are active low or high (seem to be active high, not a common decoder design).

I was new to this forum, and therefore hadnt seen how everybody just copies the code here, that makes perfect sense though, so my appologies :slight_smile:
I have followed your advice and changed and have adjusted my code. It looks like this now:

#define BAUD_RATE           115200
#define ROW_COUNT          7
#define COLUMN_COUNT     5

#define PIN_ADC_INPUT                  A0
#define PIN_SHIFT_REGISTER_DATA   2
#define PIN_SHIFT_REGISTER_CLOCK 3
#define PIN_MUX_CHANNEL_0       4  //channel pins 0, 1, 2, etc must be wired to consecutive Arduino pins
#define PIN_MUX_CHANNEL_1         5
#define PIN_MUX_CHANNEL_2         6
#define PIN_MUX_INHIBIT_0         7  //inhibit = active low enable. All mux IC enables must be wired to consecutive Arduino pins


#define SET_SR_DATA_HIGH()        PORTD|=B00000100
#define SET_SR_DATA_LOW()         PORTD&=~B00000100
#define SET_SR_CLK_HIGH()         PORTD|=B00001000
#define SET_SR_CLK_LOW()          PORTD&=~B00001000

#define ROWS_PER_MUX              8
#define MUX_COUNT                   1
#define CHANNEL_PINS_PER_MUX  3

#define PACKET_END_BYTE           0xFF
#define MAX_SEND_VALUE            254  //reserve 255 (0xFF) to mark end of packet
#define COMPRESSED_ZERO_LIMIT     254
#define MIN_SEND_VALUE            1    //values below this threshold will be treated and sent as zeros

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

/**********************************************************************************************************
* GLOBALS
**********************************************************************************************************/
int current_enabled_mux = MUX_COUNT - 1;  //init to number of last mux so enabled mux increments to first mux on first scan.
int compressed_zero_count = 0;


/**********************************************************************************************************
* setup()
**********************************************************************************************************/
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);
 
  
  sbi(ADCSRA,ADPS2);  //set ADC prescaler to CLK/16
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
}


/**********************************************************************************************************
* loop()
**********************************************************************************************************/
void loop()
{
  compressed_zero_count = 0;
  for(int i = 0; i < ROW_COUNT; i ++)
  {
    setRow(i);
    shiftColumn(true);
    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);
      sendCompressed(send_reading);
    }
  }
  if(compressed_zero_count > 0)
  {
    Serial.write((byte) 0);
    Serial.write((byte) compressed_zero_count);
  }
  Serial.write((byte) PACKET_END_BYTE);
}


/**********************************************************************************************************
* setRow() - Enable single mux IC and channel to read specified matrix row. digitalWrite() have not been
* replaced in this function, as mux changes are relatively infrequent.
**********************************************************************************************************/
void setRow(int row_number)
{
  if((row_number % ROWS_PER_MUX) == 0)  //We've reached channel 0 of a mux IC, so disable the previous mux IC, and enable the next mux IC
  {
    digitalWrite(PIN_MUX_INHIBIT_0 + current_enabled_mux, HIGH);  //This offset is why mux inhibits must be wired to consecutive Arduino pins
    current_enabled_mux ++;
    if(current_enabled_mux >= MUX_COUNT)
    {
      current_enabled_mux = 0;
    }
    digitalWrite(PIN_MUX_INHIBIT_0 + current_enabled_mux, LOW);  //enable the next mux, active 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);
    }
  }
}


/**********************************************************************************************************
* shiftColumn() - Shift out a high bit to drive first column, or increment column by shifting out a low
* bit to roll high bit through cascaded shift register outputs. digitalWrite() has been replaced with direct
* port manipulation macros, as this function performs the vast majority of pin writes
**********************************************************************************************************/
void shiftColumn(boolean is_first)
{
  if(is_first)
  {
    SET_SR_DATA_HIGH();
  }
  SET_SR_CLK_HIGH();
  SET_SR_CLK_LOW();
  if(is_first)
  {
    SET_SR_DATA_LOW();
  }
}


/**********************************************************************************************************
* sendCompressed() - If value is nonzero, send it via serial terminal as a single byte. If value is zero,
* increment zero count. The current zero count is sent and cleared before the next nonzero value
**********************************************************************************************************/
void sendCompressed(byte value)
{
  if(value < MIN_SEND_VALUE)
  {
    if(compressed_zero_count < (COMPRESSED_ZERO_LIMIT - 1))
    {
      compressed_zero_count ++;
    }
    else
    {
      Serial.write((byte) 0);
      Serial.write((byte) COMPRESSED_ZERO_LIMIT);
      compressed_zero_count = 0; 
    }
  }
  else
  {
    if(compressed_zero_count > 0)
    {
      Serial.write((byte) 0);
      Serial.write((byte) compressed_zero_count);
      compressed_zero_count = 0;
    }
    if(value > MAX_SEND_VALUE)
    {
       Serial.write((byte) MAX_SEND_VALUE);
    }
    else
    {
       Serial.write((byte) value);
    }
  }
}[code]

[/code]

Now I would like to simplify my code as you mentioned above was possible, but I am not sure which functions I could replace or delete for the code to function well.
For example, if I only have one MUX, could I delete the function of current_enabled_MUX? and if so, what could I replace it with to enable to only MUX I have?
Is there any other function I should delete, taking in count the fact that I am only using one instead of 2 components for MUX and Shiftregister?

I am doing some reasearch on my own and trying to figure it out and getting used to this programming language, but I am a complete begginner and I am very thankful for any help you xould provide!

To enable your only mux permanently, tie its enable (inhibit?) pin to Gnd (low), instead of to pin PIN_MUX_INHIBIT0.

You can check all occurrences of PIN_MUX_INHIBIT0, and of current_enabled_mux, which is a constant (zero) now. In detail the first if-statement in setRow() can be deleted, including the { ... } block immediately following it.

When you undefine (remove) MUX_COUNT and PIN_MUX_INHIBIT0, the compiler alerts you of all further uses of these identifiers in code. In most cases the offending statements can be simply removed. When you have removed the declaration of current_enabled_mux this way, and no further compilation errors are reported, you're done.

Hello everybody,

The following code is one adapted to get the signal of a pressure sensor matrix array consisting of 7 rows and 5 columns. The circuit is made up of one multiplexer, and one shift register.
I am having some trouble trying to incorporate a map function into my code (dont even know if its possible?)

I have the following code:

#define BAUD_RATE                 115200
#define ROW_COUNT                 7
#define COLUMN_COUNT              5

#define PIN_ADC_INPUT             A0
#define PIN_SHIFT_REGISTER_DATA   2
#define PIN_SHIFT_REGISTER_CLOCK  3
#define PIN_MUX_CHANNEL_0         4  //channel pins 0, 1, 2, etc must be wired to consecutive Arduino pins
#define PIN_MUX_CHANNEL_1         5
#define PIN_MUX_CHANNEL_2         6



#define SET_SR_DATA_HIGH()        PORTD|=B00000100
#define SET_SR_DATA_LOW()         PORTD&=~B00000100
#define SET_SR_CLK_HIGH()         PORTD|=B00001000
#define SET_SR_CLK_LOW()          PORTD&=~B00001000

#define ROWS_PER_MUX              8
#define CHANNEL_PINS_PER_MUX      3

#define PACKET_END_BYTE           0xFF
#define MAX_SEND_VALUE            254  //reserve 255 (0xFF) to mark end of packet
#define COMPRESSED_ZERO_LIMIT     254
#define MIN_SEND_VALUE            1    //values below this threshold will be treated and sent as zeros

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

/**********************************************************************************************************
* GLOBALS
**********************************************************************************************************/

int compressed_zero_count = 0;


/**********************************************************************************************************
* setup()
**********************************************************************************************************/
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);
 
 
  
  sbi(ADCSRA,ADPS2);  //set ADC prescaler to CLK/16
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
}


/**********************************************************************************************************
* loop()
**********************************************************************************************************/
void loop()
{
  compressed_zero_count = 0;
  for(int i = 0; i < ROW_COUNT; i ++)
  {
    setRow(i);
    shiftColumn(true);
    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);
      sendCompressed(send_reading);
    }
  }
  if(compressed_zero_count > 0)
  {
    Serial.write((byte) 0);
    Serial.write((byte) compressed_zero_count);
  }
  Serial.write((byte) PACKET_END_BYTE);
}


/**********************************************************************************************************
* shiftColumn() - Shift out a high bit to drive first column, or increment column by shifting out a low
* bit to roll high bit through cascaded shift register outputs. digitalWrite() has been replaced with direct
* port manipulation macros, as this function performs the vast majority of pin writes
**********************************************************************************************************/
void shiftColumn(boolean is_first)
{
  if(is_first)
  {
    SET_SR_DATA_HIGH();
  }
  SET_SR_CLK_HIGH();
  SET_SR_CLK_LOW();
  if(is_first)
  {
    SET_SR_DATA_LOW();
  }
}

/**********************************************************************************************************
* sendCompressed() - If value is nonzero, send it via serial terminal as a single byte. If value is zero,
* increment zero count. The current zero count is sent and cleared before the next nonzero value
**********************************************************************************************************/
void sendCompressed(byte value)
{
  if(value < MIN_SEND_VALUE)
  {
    if(compressed_zero_count < (COMPRESSED_ZERO_LIMIT - 1))
    {
      compressed_zero_count ++;
    }
    else
    {
      Serial.write((byte) 0);
      Serial.write((byte) COMPRESSED_ZERO_LIMIT);
      compressed_zero_count = 0; 
    }
  }
  else
  {
    if(compressed_zero_count > 0)
    {
      Serial.write((byte) 0);
      Serial.write((byte) compressed_zero_count);
      compressed_zero_count = 0;
    }
    if(value > MAX_SEND_VALUE)
    {
       Serial.write((byte) MAX_SEND_VALUE);
    }
    else
    {
       Serial.write((byte) value);
    }
  }
}

My issue is the following: the output singnal that i get is in bytes, but because the project is about a pressure sensor I would like to give my answer in force units (newtons).

the MIN_SEND_VALUE set to 1 byte would correspond to 1 Newton of force applied
and the MAX_SEND_VALUE set to 254 bytes corresponds in my sensor to the maximal force which is 135 Newton.

I dont know how to, or better said, where I would have to adapt/change my code to give this relationship between Byte-Force.

Could it be possible to map values between my minimum and my maximum (2 to 253 Bytes) being the case that I have the corresponding values in Force units?

I hope I am making sense here.

Any help would be really appreciated!

map((int) yourByte, 1,254,1,135);

Will transform your value that is between your min (1) and max (254) to a number with linear relation between 1 to 135

Of course use your #defined values not constant for better readability

Hello everybody,

The following code is one adapted to get the signal of a pressure sensor matrix array consisting of 7 rows and 5 columns. The circuit is made up of one multiplexer, and one shift register.
I am having some trouble trying to incorporate a map function into my code (dont even know if its possible?)

I have the following code:

[code]#define BAUD_RATE                 115200
#define ROW_COUNT                 7
#define COLUMN_COUNT              5

#define PIN_ADC_INPUT             A0
#define PIN_SHIFT_REGISTER_DATA   2
#define PIN_SHIFT_REGISTER_CLOCK  3
#define PIN_MUX_CHANNEL_0         4  //channel pins 0, 1, 2, etc must be wired to consecutive Arduino pins
#define PIN_MUX_CHANNEL_1         5
#define PIN_MUX_CHANNEL_2         6



#define SET_SR_DATA_HIGH()        PORTD|=B00000100
#define SET_SR_DATA_LOW()         PORTD&=~B00000100
#define SET_SR_CLK_HIGH()         PORTD|=B00001000
#define SET_SR_CLK_LOW()          PORTD&=~B00001000

#define ROWS_PER_MUX              8
#define CHANNEL_PINS_PER_MUX      3

#define PACKET_END_BYTE           0xFF
#define MAX_SEND_VALUE            254  //reserve 255 (0xFF) to mark end of packet
#define COMPRESSED_ZERO_LIMIT     254
#define MIN_SEND_VALUE            1    //values below this threshold will be treated and sent as zeros

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

/**********************************************************************************************************
* GLOBALS
**********************************************************************************************************/

int compressed_zero_count = 0;


/**********************************************************************************************************
* setup()
**********************************************************************************************************/
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);
 
 
  
  sbi(ADCSRA,ADPS2);  //set ADC prescaler to CLK/16
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
}


/**********************************************************************************************************
* loop()
**********************************************************************************************************/
void loop()
{
  compressed_zero_count = 0;
  for(int i = 0; i < ROW_COUNT; i ++)
  {
    setRow(i);
    shiftColumn(true);
    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);
      sendCompressed(send_reading);
    }
  }
  if(compressed_zero_count > 0)
  {
    Serial.write((byte) 0);
    Serial.write((byte) compressed_zero_count);
  }
  Serial.write((byte) PACKET_END_BYTE);
}


/**********************************************************************************************************
* shiftColumn() - Shift out a high bit to drive first column, or increment column by shifting out a low
* bit to roll high bit through cascaded shift register outputs. digitalWrite() has been replaced with direct
* port manipulation macros, as this function performs the vast majority of pin writes
**********************************************************************************************************/
void shiftColumn(boolean is_first)
{
  if(is_first)
  {
    SET_SR_DATA_HIGH();
  }
  SET_SR_CLK_HIGH();
  SET_SR_CLK_LOW();
  if(is_first)
  {
    SET_SR_DATA_LOW();
  }
}

/**********************************************************************************************************
* sendCompressed() - If value is nonzero, send it via serial terminal as a single byte. If value is zero,
* increment zero count. The current zero count is sent and cleared before the next nonzero value
**********************************************************************************************************/
void sendCompressed(byte value)
{
  if(value < MIN_SEND_VALUE)
  {
    if(compressed_zero_count < (COMPRESSED_ZERO_LIMIT - 1))
    {
      compressed_zero_count ++;
    }
    else
    {
      Serial.write((byte) 0);
      Serial.write((byte) COMPRESSED_ZERO_LIMIT);
      compressed_zero_count = 0; 
    }
  }
  else
  {
    if(compressed_zero_count > 0)
    {
      Serial.write((byte) 0);
      Serial.write((byte) compressed_zero_count);
      compressed_zero_count = 0;
    }
    if(value > MAX_SEND_VALUE)
    {
       Serial.write((byte) MAX_SEND_VALUE);
    }
    else
    {
       Serial.write((byte) value);
    }
  }
}

[/code]

My issue is the following: the output singnal that i get is in bytes, but because the project is about a pressure sensor I would like to give my answer in force units (newtons).

the MIN_SEND_VALUE set to 1 byte would correspond to 1 Newton of force applied
and the MAX_SEND_VALUE set to 254 bytes corresponds in my sensor to the maximal force which is 135 Newton.

I dont know how to, or better said, where I would have to adapt/change my code to give this relationship between Byte-Force.

Could it be possible to map values between my minimum and my maximum (2 to 253 Bytes) being the case that I have the corresponding values in Force units?

I hope I am making sense here.

Any help would be really appreciated!

thank you very much for your quick response! what i still dont understand is where in the code, or better said to which variable i can apply this mapping function. I am new to programming with arduino, and therefore i amhaving trouble seeing which variable exactly gives my output signal (is it "value"?)

In your sendCompressed function yes it's value but it comes from send_reading

Be careful as all the testing against bounds in the sendCompressed function is not the mapped value

Try changing this

     byte send_reading = (byte) (lowByte(raw_reading >> 2));

to this

      byte send_reading = map(raw_reading, 0, 1023, 0, 135);

Could it be possible to map values between my minimum and my maximum (2 to 253 Bytes)

You are not sending between 2 bytes and 253 bytes. You are sending one single byte containing a value between 2 and 253.

Hello everybody,

I am a newby in arduino and I am trying to get a project up and running but I am having some troubles with it, I hope you can help me out here.

I am trying to get the output signal of a pressure sensor matrix (7x5). My circuit consists of one multiplexer, one shiftregister and a pull up resistor, apart from the arduino Uno.

I have the following code:

#define BAUD_RATE                 115200
#define ROW_COUNT                 7
#define COLUMN_COUNT              5

#define PIN_ADC_INPUT             A0
#define PIN_SHIFT_REGISTER_DATA   2
#define PIN_SHIFT_REGISTER_CLOCK  3
#define PIN_MUX_CHANNEL_0         4  //channel pins 0, 1, 2, etc must be wired to consecutive Arduino pins
#define PIN_MUX_CHANNEL_1         5
#define PIN_MUX_CHANNEL_2         6



#define SET_SR_DATA_HIGH()        PORTD|=B00000100
#define SET_SR_DATA_LOW()         PORTD&=~B00000100
#define SET_SR_CLK_HIGH()         PORTD|=B00001000
#define SET_SR_CLK_LOW()          PORTD&=~B00001000

#define ROWS_PER_MUX              8
#define CHANNEL_PINS_PER_MUX      3

#define PACKET_END_BYTE           0xFF
#define MAX_SEND_VALUE            254  //reserve 255 (0xFF) to mark end of packet
#define COMPRESSED_ZERO_LIMIT     254
#define MIN_SEND_VALUE            1    //values below this threshold will be treated and sent as zeros

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

/**********************************************************************************************************
* GLOBALS
**********************************************************************************************************/

int compressed_zero_count = 0;


/**********************************************************************************************************
* setup()
**********************************************************************************************************/
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);
 
 
  
  sbi(ADCSRA,ADPS2);  //set ADC prescaler to CLK/16
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
}


/**********************************************************************************************************
* loop()
**********************************************************************************************************/
void loop()
{
  compressed_zero_count = 0;
  for(int i = 0; i < ROW_COUNT; i ++)
  {
    setRow(i);
    shiftColumn(true);
    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);
      sendCompressed(send_reading);
    }
  }
  if(compressed_zero_count > 0)
  {
    Serial.write((byte) 0);
    Serial.write((byte) compressed_zero_count);
  }
  Serial.write((byte) PACKET_END_BYTE);
}


/**********************************************************************************************************
* shiftColumn() - Shift out a high bit to drive first column, or increment column by shifting out a low
* bit to roll high bit through cascaded shift register outputs. digitalWrite() has been replaced with direct
* port manipulation macros, as this function performs the vast majority of pin writes
**********************************************************************************************************/
void shiftColumn(boolean is_first)
{
  if(is_first)
  {
    SET_SR_DATA_HIGH();
  }
  SET_SR_CLK_HIGH();
  SET_SR_CLK_LOW();
  if(is_first)
  {
    SET_SR_DATA_LOW();
  }
}

/**********************************************************************************************************
* sendCompressed() - If value is nonzero, send it via serial terminal as a single byte. If value is zero,
* increment zero count. The current zero count is sent and cleared before the next nonzero value
**********************************************************************************************************/
void sendCompressed(byte value)
{
  if(value < MIN_SEND_VALUE)
  {
    if(compressed_zero_count < (COMPRESSED_ZERO_LIMIT - 1))
    {
      compressed_zero_count ++;
    }
    else
    {
      Serial.write((byte) 0);
      Serial.write((byte) COMPRESSED_ZERO_LIMIT);
      compressed_zero_count = 0; 
    }
  }
  else
  {
    if(compressed_zero_count > 0)
    {
      Serial.write((byte) 0);
      Serial.write((byte) compressed_zero_count);
      compressed_zero_count = 0;
    }
    if(value > MAX_SEND_VALUE)
    {
       Serial.write((byte) MAX_SEND_VALUE);
    }
    else
    {
       Serial.write((byte) value);
    }
  }
}

My problem here is that since its a pressure mapping system that I am trying to create, I would like to get my output singnal in force units instead of bytes.

I have a minimum force value of ! Newton, which corresponds to 1 (in byte value), and a maximum force value of 135 Newton(which corresponds to 254 , in bytes value) Can somebody please helo me out with the conversion of my output signal from Byte to Newton? Im very lost here and any help would be very appreciated!

Hello everybody,

I have the following situation:

I need to read the force applied on a pressure sensor matrix, consisting of 7 rows and 5 columns. The sensor is made up of a PCB and a FSR material, and for the data acquisition I am working with an Arduino Uno, a multiplexer and a shift register.
I have the following code:

#define BAUD_RATE                 115200
#define ROW_COUNT                 7
#define COLUMN_COUNT              5

#define PIN_ADC_INPUT             A0
#define PIN_SHIFT_REGISTER_DATA   2
#define PIN_SHIFT_REGISTER_CLOCK  3
#define PIN_MUX_CHANNEL_0         4  //channel pins 0, 1, 2, etc must be wired to consecutive Arduino pins
#define PIN_MUX_CHANNEL_1         5
#define PIN_MUX_CHANNEL_2         6



#define SET_SR_DATA_HIGH()        PORTD|=B00000100
#define SET_SR_DATA_LOW()         PORTD&=~B00000100
#define SET_SR_CLK_HIGH()         PORTD|=B00001000
#define SET_SR_CLK_LOW()          PORTD&=~B00001000

#define ROWS_PER_MUX              8
#define CHANNEL_PINS_PER_MUX      3

#define PACKET_END_BYTE           0xFF
#define MAX_SEND_VALUE            254  //reserve 255 (0xFF) to mark end of packet
#define COMPRESSED_ZERO_LIMIT     254
#define MIN_SEND_VALUE            1    //values below this threshold will be treated and sent as zeros

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

/**********************************************************************************************************
* GLOBALS
**********************************************************************************************************/

int compressed_zero_count = 0;


/**********************************************************************************************************
* setup()
**********************************************************************************************************/
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);
 
 
  
  sbi(ADCSRA,ADPS2);  //set ADC prescaler to CLK/16
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
}


/**********************************************************************************************************
* loop()
**********************************************************************************************************/
void loop()
{
  compressed_zero_count = 0;
  for(int i = 0; i < ROW_COUNT; i ++)
  {
    setRow(i);
    shiftColumn(true);
    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);
      sendCompressed(send_reading);
    }
  }
  if(compressed_zero_count > 0)
  {
    Serial.write((byte) 0);
    Serial.write((byte) compressed_zero_count);
  }
  Serial.write((byte) PACKET_END_BYTE);
}


/**********************************************************************************************************
* shiftColumn() - Shift out a high bit to drive first column, or increment column by shifting out a low
* bit to roll high bit through cascaded shift register outputs. digitalWrite() has been replaced with direct
* port manipulation macros, as this function performs the vast majority of pin writes
**********************************************************************************************************/
void shiftColumn(boolean is_first)
{
  if(is_first)
  {
    SET_SR_DATA_HIGH();
  }
  SET_SR_CLK_HIGH();
  SET_SR_CLK_LOW();
  if(is_first)
  {
    SET_SR_DATA_LOW();
  }
}

/**********************************************************************************************************
* sendCompressed() - If value is nonzero, send it via serial terminal as a single byte. If value is zero,
* increment zero count. The current zero count is sent and cleared before the next nonzero value
**********************************************************************************************************/
void sendCompressed(byte value)
{
  if(value < MIN_SEND_VALUE)
  {
    if(compressed_zero_count < (COMPRESSED_ZERO_LIMIT - 1))
    {
      compressed_zero_count ++;
    }
    else
    {
      Serial.write((byte) 0);
      Serial.write((byte) COMPRESSED_ZERO_LIMIT);
      compressed_zero_count = 0; 
    }
  }
  else
  {
    if(compressed_zero_count > 0)
    {
      Serial.write((byte) 0);
      Serial.write((byte) compressed_zero_count);
      compressed_zero_count = 0;
    }
    if(value > MAX_SEND_VALUE)
    {
       Serial.write((byte) MAX_SEND_VALUE);
    }
    else
    {
       Serial.write((byte) value);
    }
  }
}

My output signal is presented as a byte with values between o and 254 (0 when theres no pressure applied, 254 for the maximum pressure).

I would like to plot this data into MATLAB or Python on a contour plot, where my preassure peaks are showed, but in a scala of force units.
I would need help on the MATLAB plotting as well.

My corresponding minimum force value (when it shows 0 in bytes) is 1 Newton
My corresponding maximum force value (for 254 in bytes) is 135 Newton.

If anybody has any idea on how to do this, and has the time, I would pay for your help, as I am nowhere near getting this project up and running and it is very urgent!

Thank you for taking the time to read this

Hi,

you missed an "[" on /code tag

From saying you need help on PC side program you mean the arduino is already sending the right codes via serial line?

Hi,

I modified the previous post, I hope the code and my text are shown separately now!

I need guidance on the best way to do this, my arduino code is not yet running properly.

I took a code from an example of a tutorial of a 16x16 matrix sensor array, and adapted it to my situation.
their code was the following:

#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  //channel pins 0, 1, 2, etc must be wired to consecutive Arduino pins
#define PIN_MUX_CHANNEL_1         5
#define PIN_MUX_CHANNEL_2         6
#define PIN_MUX_INHIBIT_0         7  //inhibit = active low enable. All mux IC enables must be wired to consecutive Arduino pins
#define PIN_MUX_INHIBIT_1         8

#define SET_SR_DATA_HIGH()        PORTD|=B00000100
#define SET_SR_DATA_LOW()         PORTD&=~B00000100
#define SET_SR_CLK_HIGH()         PORTD|=B00001000
#define SET_SR_CLK_LOW()          PORTD&=~B00001000

#define ROWS_PER_MUX              8
#define MUX_COUNT                 2
#define CHANNEL_PINS_PER_MUX      3

#define PACKET_END_BYTE           0xFF
#define MAX_SEND_VALUE            254  //reserve 255 (0xFF) to mark end of packet
#define COMPRESSED_ZERO_LIMIT     254
#define MIN_SEND_VALUE            1    //values below this threshold will be treated and sent as zeros

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

/**********************************************************************************************************
* GLOBALS
**********************************************************************************************************/
int current_enabled_mux = MUX_COUNT - 1;  //init to number of last mux so enabled mux increments to first mux on first scan.
int compressed_zero_count = 0;


/**********************************************************************************************************
* setup()
**********************************************************************************************************/
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);
  
  sbi(ADCSRA,ADPS2);  //set ADC prescaler to CLK/16
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
}


/**********************************************************************************************************
* loop()
**********************************************************************************************************/
void loop()
{
  compressed_zero_count = 0;
  for(int i = 0; i < ROW_COUNT; i ++)
  {
    setRow(i);
    shiftColumn(true);
    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);
      sendCompressed(send_reading);
    }
  }
  if(compressed_zero_count > 0)
  {
    Serial.write((byte) 0);
    Serial.write((byte) compressed_zero_count);
  }
  Serial.write((byte) PACKET_END_BYTE);
}


/**********************************************************************************************************
* setRow() - Enable single mux IC and channel to read specified matrix row. digitalWrite() have not been
* replaced in this function, as mux changes are relatively infrequent.
**********************************************************************************************************/
void setRow(int row_number)
{
  if((row_number % ROWS_PER_MUX) == 0)  //We've reached channel 0 of a mux IC, so disable the previous mux IC, and enable the next mux IC
  {
    digitalWrite(PIN_MUX_INHIBIT_0 + current_enabled_mux, HIGH);  //This offset is why mux inhibits must be wired to consecutive Arduino pins
    current_enabled_mux ++;
    if(current_enabled_mux >= MUX_COUNT)
    {
      current_enabled_mux = 0;
    }
    digitalWrite(PIN_MUX_INHIBIT_0 + current_enabled_mux, LOW);  //enable the next mux, active 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);
    }
  }
}


/**********************************************************************************************************
* shiftColumn() - Shift out a high bit to drive first column, or increment column by shifting out a low
* bit to roll high bit through cascaded shift register outputs. digitalWrite() has been replaced with direct
* port manipulation macros, as this function performs the vast majority of pin writes
**********************************************************************************************************/
void shiftColumn(boolean is_first)
{
  if(is_first)
  {
    SET_SR_DATA_HIGH();
  }
  SET_SR_CLK_HIGH();
  SET_SR_CLK_LOW();
  if(is_first)
  {
    SET_SR_DATA_LOW();
  }
}


/**********************************************************************************************************
* sendCompressed() - If value is nonzero, send it via serial terminal as a single byte. If value is zero,
* increment zero count. The current zero count is sent and cleared before the next nonzero value
**********************************************************************************************************/
void sendCompressed(byte value)
{
  if(value < MIN_SEND_VALUE)
  {
    if(compressed_zero_count < (COMPRESSED_ZERO_LIMIT - 1))
    {
      compressed_zero_count ++;
    }
    else
    {
      Serial.write((byte) 0);
      Serial.write((byte) COMPRESSED_ZERO_LIMIT);
      compressed_zero_count = 0; 
    }
  }
  else
  {
    if(compressed_zero_count > 0)
    {
      Serial.write((byte) 0);
      Serial.write((byte) compressed_zero_count);
      compressed_zero_count = 0;
    }
    if(value > MAX_SEND_VALUE)
    {
       Serial.write((byte) MAX_SEND_VALUE);
    }
    else
    {
       Serial.write((byte) value);
    }
  }
}

They used 2 mux and 2 shift registers instead, because for their situation one of each wasnt enough.
Since I only use one mux, i deleted all the functions accountable for enabling one mux after the other and pinned my only mux to GND on my arduino so it is always “enabled”.

apart from this and modifyinf the amount of rows and columns I didnt modify my code in any other way, but it still doesnt function and I cant recognize the issue.

I would need help with the arduino code, as well as how to read and plot my serial data into a side PC Program.

Could you help me out?

Hello once again!

I have succesfully got the force of my sensor out of a much simpler code, made to get the force just out of one sensor (instead of a matrix array of sensors, like I am trying to accomplish)
I have employed the following code which works just fine:

int fsrPin = 0;     
int fsrReading;     
int fsrForce;    

 
void setup(void) {
  Serial.begin(9600); 
}
 
void loop(void) {
  fsrReading = analogRead(fsrPin);  
  Serial.print("Analog reading = ");
  Serial.println(fsrReading);
 
 
  fsrForce = map(fsrReading, 0, 1023, 1,135 );
  Serial.print("Force reading in N = ");
  Serial.println(fsrForce);  
 
  if (fsrForce == 0) {
    Serial.println("No pressure");  
  } else {
 
delay (1000);
}
}

My question is, how can I apply this code, or one that does the same function into my more complex code (attached in previous post)?

Why do you lower the clock for the ADC ?

Is the integer value of analogRead() maximum 254 ? or is it maximum 1023 and you shift that two positions to the right ?

You could use the 'map' function. The example is almost what you need. https://www.arduino.cc/en/Reference/Map Remove the shifting.

send_reading_in_newton = map( raw_reading, 0, 1023, 0, 135);

On PC side I can help only with reading/parsing serial input from Arduino. For Arduino side program, I sent you a PM

Hello again and thank you very much for your response.

I have modified the code and tried to map between myminimum and maximum values, but I still get my final answer in values between 0 to 254, instead of in Newtons.

this is the code I am working with now :

#define BAUD_RATE                 115200
#define ROW_COUNT                 7
#define COLUMN_COUNT              5

#define PIN_ADC_INPUT             A0
#define PIN_SHIFT_REGISTER_DATA   2
#define PIN_SHIFT_REGISTER_CLOCK  3
#define PIN_MUX_CHANNEL_0         4  //channel pins 0, 1, 2, etc must be wired to consecutive Arduino pins
#define PIN_MUX_CHANNEL_1         5
#define PIN_MUX_CHANNEL_2         6



#define SET_SR_DATA_HIGH()        PORTD|=B00000100
#define SET_SR_DATA_LOW()         PORTD&=~B00000100
#define SET_SR_CLK_HIGH()         PORTD|=B00001000
#define SET_SR_CLK_LOW()          PORTD&=~B00001000

#define ROWS_PER_MUX              8
#define CHANNEL_PINS_PER_MUX      3

#define PACKET_END_BYTE           0xFF
#define MAX_SEND_VALUE            254  //reserve 255 (0xFF) to mark end of packet
#define COMPRESSED_ZERO_LIMIT     254
#define MIN_SEND_VALUE            1    //values below this threshold will be treated and sent as zeros

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

/**********************************************************************************************************
* GLOBALS
**********************************************************************************************************/

int compressed_zero_count = 0;


/**********************************************************************************************************
* setup()
**********************************************************************************************************/
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);
 
 
  
  sbi(ADCSRA,ADPS2);  //set ADC prescaler to CLK/16
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
}


/**********************************************************************************************************
* loop()
**********************************************************************************************************/
 void loop()
{
  compressed_zero_count = 0;
  for(int i = 0; i < ROW_COUNT; i ++)
  {
    setRow(i);
    shiftColumn(true);
    for(int j = 0; j < COLUMN_COUNT; j ++)
    {
      int raw_reading = analogRead(PIN_ADC_INPUT);
      byte send_reading_in_Newton = map(raw_reading, 0, 1023, 1, 135);
      shiftColumn(false);
      sendCompressed(send_reading_in_Newton);
    }
  }
  if(compressed_zero_count > 0)
  {
    Serial.write((byte) 0);
    Serial.write((byte) compressed_zero_count);
  }
  Serial.write((byte) PACKET_END_BYTE);
}


/**********************************************************************************************************
* shiftColumn() - Shift out a high bit to drive first column, or increment column by shifting out a low
* bit to roll high bit through cascaded shift register outputs. digitalWrite() has been replaced with direct
* port manipulation macros, as this function performs the vast majority of pin writes
**********************************************************************************************************/
void setRow(int row_number)
{
}


void shiftColumn(boolean is_first)
{
  if(is_first)
  {
    SET_SR_DATA_HIGH();
  }
  SET_SR_CLK_HIGH();
  SET_SR_CLK_LOW();
  if(is_first)
  {
    SET_SR_DATA_LOW();
  }
}

/**********************************************************************************************************
* sendCompressed() - If value is nonzero, send it via serial terminal as a single byte. If value is zero,
* increment zero count. The current zero count is sent and cleared before the next nonzero value
**********************************************************************************************************/
void sendCompressed(byte value)
{
  if(value < MIN_SEND_VALUE)
  {
    if(compressed_zero_count < (COMPRESSED_ZERO_LIMIT - 1))
    {
      compressed_zero_count ++;
    }
    else
    {
      Serial.write((byte) 0);
      Serial.write((byte) COMPRESSED_ZERO_LIMIT);
      compressed_zero_count = 0; 
    }
  }
  else
  {
    if(compressed_zero_count > 0)
    {
      Serial.write((byte) 0);
      Serial.write((byte) compressed_zero_count);
      compressed_zero_count = 0;
    }
    if(value > MAX_SEND_VALUE)
    {
       Serial.write((byte) MAX_SEND_VALUE);
    }
    else
    {
       Serial.write((byte) value);
    }
  }
}

I didnt change the value of my variables “MAX_SEND_VALUE” and “MIN_SEND_VALUE” which are still set respectively to 0 and 254.I tried changing them to 0 and 1023 instead but it also doesnt work. My whole code is made up of byte variables, that I dont know how to propèrly change so I get an int output signal (newtons) how i want it to be.

You actually did type the full "send_reading_in_Newton" :smiley_cat: I don't understand your sketch very well. Sometimes the "value" is send, and sometimes the "compressed_zero_count" is send. If you get 254, how do you know which one it is ?

You can solve these things by adding more Serial.print.

  byte send_reading_in_Newton = map(raw_reading, 0, 1023, 1, 135);
  Serial.print("The variable with the silly name called send_reading_in_Newton is now : ");
  Serial.println( send_reading_in_Newton);

Did you know that Arduino has bitSet() and bitClear(). https://www.arduino.cc/en/Reference/BitSet They result into a single assembly instruction. Your defines for SET_SR_DATA_HIGH and the others, and also for sbi and cbi could be the bitSet() and bitClear().