Go Down

Topic: Reading massive sensor outputs with high speed (Read 395 times) previous topic - next topic

erfan

Hi,

Hope you do very well.

I am doing research on human-induced vibrationand I am currently trying to design a sensor mat which has 2000 sensors to capture dynamic load of people when they are walking on that mat.

each sensor needs to be read with 200 Hz speed. As 3200 analog input is not possible! we decided to scan the sensors with high speed (like video cameras) to read the sensor outputs with lesser analog input channels.

here is the plan: 4 mat each contains 800 sensors. A matrix of sensors with 16 columns and 50 rows. we want to use Arduino mega 2560 to get the data and transfer it to a PC. I have written the below code to scan the sensors but Arduino seems very slow..

how the program works:
At each time increment, one digital output (50 digital pin) releases the power to its corresponding row of sensors (16 sensors) each of which connected to an analog input. so we use 50 digital output and 16 analog input to scan sensors.

My question: Is there any way to increase the speed?
we need to read 800 sensors * 200 Hz * each outtput is 4 digits * each digit 2 bytes = 10.24 Mbits/second

If Arduino is not capable of doing that, Do you have any suggestions which hardware I can use?

Much regards,
Erfan   

/* TEST 06
 
This program scans the matrix of sensors to get data.

Assumptions:
   - A matrix of sensors consist of 800 sensors arranged in the form of 16 columns (Analog inputs) and 50 rows (Digital outputs)
   - 50 Digital output to supply +5 volts power for each row of sensors
   - 16 Analog inouts to read the output of sensors
   - At each time increment, one digital output releases the power to its corresponding row of sensors (16 sensors) each of which connected to an analog input.
     So at each time increment each analog input read a number.
   - Sensor numbering: S(Row - digital output)(column - analog input) : S2006 means the sensor which is connected to digital pin 20 and analog pin 06.
   - "i" index represents rows and "j" index represents columns 

Connect one end of FSR to power (+5V in this case), the other end to Analog 0.
Then connect one end of a 10K resistor from Analog 0 to ground

*/

//Define Pins 
int digitalPin [50]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
                     17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
                     33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49};
int analogPin [16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

//Define Variables
unsigned int analogFSRReading [50][16];      // The analog reading from the FSR resistor divider
unsigned long startTime = 0;                 // Records the starting Time of each complete scan loop
unsigned long endTime = 0;                   // Records the finishing Time of each complete scan loop
unsigned long elapsedTime = 0;               // Records the duration of each complete scan loop
int counter;                                 // Loop Counter
int i;                                       // Loop counter - rows - digital outputs
int j;                                       // Loop counter - columns - analog inputs


void setup(void) {
 
  Serial.begin(115200);   // We'll send debugging information via the Serial monitor - I have changed the corresponding com port speed from device manager
                          // to match this speed.
                         
   for (int counter=0; counter <= 49; counter++){       
      pinMode(digitalPin [counter], OUTPUT);      // sets the digital pin as output     
    }
                           
}


void loop(void) {

  startTime = micros(); // Records the time when loop starts
 
  for (int i=0; i <= 49; i++){         // scans rows one by one
    digitalWrite(digitalPin , HIGH);   // Sets the digital pin voltage to 5V
   
    for (int j=0; j <= 15; j++){       // scans columns one by one
     
      // Displaying sensor ID
      //Serial.print("Sensor (");
      //Serial.print(i);
      //Serial.print(",");
      //Serial.print(j);
      //Serial.println(")");
     
      // Analog Reading from FSR - ranges between 0 to 1023
      analogFSRReading [j] = analogRead(analogPin [j]);    // read the input pin 
      //Serial.print("Analog reading = ");
      Serial.println(analogFSRReading [j]);   
      //Serial.println("--------------------");
     
    } 
   
    digitalWrite(digitalPin , LOW);   // Sets the digital pin voltage to 0

  }
 
  // Printing time duration
  endTime = micros(); // Records the time when loop finishes
  elapsedTime = endTime - startTime;
  Serial.print("Single loop (reading 800 sensors and feeding outputs to serial port) duration in micro-seconds: ");
  Serial.println(elapsedTime, DEC);
  Serial.println("--------------------");
  delay(10000); // just to see the speed and elapsed time
}

cr0sh

Maybe you should offload the work - a couple of suggestions:

1) Use multiple Arduinos - one per mat, or even more (may 4 per mat) - then use SPI/I2C to transfer to "master Arduino" which communicates to the PC.
2) Instead of row/column scanning with the Arduino, use a cascaded series of decimal counter ICs (you send a pulse, and a pin is activated in turn; there is an "overflow" pin that is connected to the next in the series, with the final overflow connected to a master reset or the like - there's various way to do this).

Using both of these techniques, you'll simplify your wiring and likely your coding. You'll probably improve the speed. Now, whether this will output properly "real time" or not, I don't know; if you can split the tasks up, you can have the Arduinos of the mat communicating back to the master Arduino, and only send data (with an appropriate "Arduino ID") from the Arduinos with "new data" (because when a person or person's are walking across the mat, not all of the Arduino's and sensors will be activated at the same time - so you reduce the amount of data being sent and processed this way).

Divide and conquer!

:D
I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

robtillaart


2000 sensors @200 Hz is 400K analogreadings per second.
I don't know the MEGA but an UNO has only one ADC on board which is multiplexed and can do ~8.5 K readings with 100% CPU load @10bits.

How many bits per sample do you want? because The Arduino allows to do analogRead faster for the prize of some precision. I have some code that can do 50K samples per second and IIRC it still had 7-8 bits prec.

Cr0sh answer is very good.

I would start sampling only 1 in 100 sensors (~20) at strategic places constantly. And do a finer grain sampling if one of the 20 is triggered. Dividing the area in 16 squares and if the midpoint is triggered => sample the whole square.

2000 = 40 x 50 (assumption)  => 20 squares of 10x10 => 20 midpoints

ON the other hand take time to look at other uProc like the mbed that work at higher clockspeeds . Think you will need that.

my 2 cents,





Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Magician

Quote
we need to read 800 sensors * 200 Hz * each outtput is 4 digits * each digit 2 bytes = 10.24 Mbits/second
I'm not "comprehend" where 4 digit x 2 bytes come from, it's 64-bit ADC?
Probably , arduino could scan 800 x 200 = 160 ksps at the maximum available ADCs preselector speed settings, 8-bit resolution and if sensors have low output impedance ( < 1 kOhm or so) but it still leave a question how this high rate data flow 160 kByte/sec. transfer to PC. The solution I can see, is transfer "active region" data only, about "foot" size area instead of all mat, and in order arduino be capable to track or "pre-filter" active region ADC has to be "precise" configured in interrupt driven mode, leaving CPU do a "tracking" as there would be about 6 usec only to do a math....

Go Up