digital input storage

Hi! I want to create a program in arduino that keeps a log of the digital inputs. I was thinking of using a table, but from what I've searched that isn't really a good idea in ardino. I don't need to have the data stored after I shut down the device, so no need to use the eprom.
Since I can't really save single bits I'm worried something like this would make me use all the memory really fast!
Btw, the data acquired is going to be analyzed matlab, using interruptions. That part is mostly done.
Any suggestion would be great!

I need 12 pins. How do I do that?!

I need 12 pins. How do I do that?!

Use two bytes, or an int.

Why do you need to save this information? It seems that knowing WHEN the change happens would be more important than what the state is periodically.

How many times do you need to save the data? How often?

PaulS:
Use two bytes, or an int.

Why do you need to save this information? It seems that knowing WHEN the change happens would be more important than what the state is periodically.

How many times do you need to save the data? How often?

I'm using the digital inputs to store the outputs from a PLC. The response time from the plc is 0.6ms, so I need to store data as close to that as possible. I guess I only need to save a state when it changes. And I still need to figure out how to also save when the state change occurs. Thanks for the help!

What do you think about the following?

#define NUM_PINS 12

uint8_t pins[NUM_PINS] = {1,2,3,4,5,6,7,8,9,10,11,12};

// the setup routine runs once when you press reset:
void setup() {
 Serial.begin(9600);
 // initialize the digital pins as inputs
 for (uint8_t i = 0; i < NUM_PINS; i++) {
 pinMode(pins[i], INPUT);
 }
}

// 0000 0000 0000 0000
int lastReading = 0x0000;

void loop() {
 bool change = false;
 
 for (uint8_t i = 0; i < NUM_PINS; i++) {
 // pick pin last known state
 bool lastState = 0x01 & (lastReading >> i);
 // read current state
 bool pinState = digitalRead(pins[i]);
 // check pin state change
 if (pinState != lastState) {
 change = true;
 lastReading ^= (0x01 << i);
 }
 }
 
 // if change is true at least one pin state changed
 // and lastReading will contain pins states
 if (change) {
 Serial.println("changed");
 Serial.println(lastReading, HEX);
 }
}

You can store the lastReading integer along with the current time, but without having an RTC module you will only have the time elapse since last reset.

What do you think about the following?

Not much. Using pin 1 for Serial and input is not going to work.

@sprk, you have not told us how many samples you need to store before they are uploaded to Matlab.

...R

Robin2:
@sprk, you have not told us how many samples you need to store before they are uploaded to Matlab.

...R

That really depends, but it only needs to store the changes and time when they happen. I doubt it would ever run for more then 5 minutes, with probably a lot less then 100 state changes.
It's more of a time thing, during the time before it receives an interruption it is suppose to keep running and saving changes in the inputs.

Sorry for taking so long to respond, I was sick.

That seems to suggest you want to read the values of a number of digital pins and store the values everytime there is a change - for up to 100 changes. I'm guessing that means that this

0000
0010
0010
0100
0100
0001

would result in this saved data - only saving when the value changes
0000
0010
0100
0001

which does not seem very useful to me

The simplest system is surely to read a port using PINx (where x is the port number), mask off any irrelevant bits and save the value in an array if the value had changed. You could easily do that for a few ports.

...R

Instead of using an "int" for your 12 bits, thereby wasting 25% of your precious RAM, some simple arithmetic, shift and mask operations as buffer management would allow you to store more readings

It's more of a time thing, during the time before it receives an interruption it is suppose to keep running and saving changes in the inputs.

That is not going to happen. When "it" (whatever the hell it is) receives an interrupt, "it" responds to the interrupt EXCLUSIVELY. If you are farting around in the interrupt processing routine, so that polling the pins fails to detect all the changes, then you need to fix the interrupt service routine.

It's time to take the tap dancing shoes off. Your tap dancing is quite good, but it is distracting. What is it you are trying to accomplish? What is causing the interrupts? How, and when, are you reading the other pins? How, and when, are you planning to catch up on the data that you are late responding to?

PaulS:
That is not going to happen. When "it" (whatever the hell it is) receives an interrupt, "it" responds to the interrupt EXCLUSIVELY. If you are farting around in the interrupt processing routine, so that polling the pins fails to detect all the changes, then you need to fix the interrupt service routine.

Yes, I know, when it receives an interrupt it is not suppose to keep reading the digital pins or do anything else.

PaulS:
It's time to take the tap dancing shoes off. Your tap dancing is quite good, but it is distracting. What is it you are trying to accomplish? What is causing the interrupts? How, and when, are you reading the other pins? How, and when, are you planning to catch up on the data that you are late responding to?

The interrupt just asks for the variables that contain the log from the the digital inputs. It's caused by a serial event, simple stuff!

From @rlogiacco code I was able to write a first draft

#define NUM_PINS 4
#define DATA_SIZE 300


uint8_t pins[NUM_PINS] = {40,41,42,43};
uint8_t data[DATA_SIZE];
unsigned long time_data[DATA_SIZE];

// the setup routine runs once when you press reset:
void setup() {
 Serial.begin(9600);
 // initialize the digital pins as inputs
 for (uint8_t i = 0; i < NUM_PINS; i++) {
 pinMode(pins[i], INPUT);
 }
}

// 0000 0000 0000 0000
int lastReading = 0;
int q = 0;
bool ini = false;
unsigned long time;
unsigned long time_ini;

void loop() {
 // initialize time variable
 if (ini == false) {
   time_ini = millis();
   ini = true; }
  
 bool change = false;
 for (uint8_t i = 0; i < NUM_PINS; i++) {
	bool lastState = bitRead(lastReading, i);
	bool pinState = digitalRead(pins[i]);
	if (pinState != lastState) {
		// if change is true record time
		time = millis();
		change = true;
		bitWrite(lastReading, i, pinState);
	}
 }
   
 // if change is true at least one pin state changed
 // and lastReading will contain pins states
 if (change) {
	data[q] = lastReading;
	time_data[q] = time - time_ini;
	Serial.println("changed");
	Serial.println(data[q], BIN);
	Serial.println(time_data[q], DEC);
	Serial.println();
	q++;
      }
}

I didn't use dynamic arrays because I remember reading that arduino doesn't work well with mallocs and that kind of stuff. Is that true?

I didn't use dynamic arrays because I remember reading that arduino doesn't work well with mallocs and that kind of stuff. Is that true?

No. Dynamic memory allocation works just fine, as long as you don't allocate and free tiny amounts at a time. Doing that can result in Swiss cheese.

Thanks PaulS, I will try to implement that.

A bit unrelated, When implementing the code for more inputs I realized I was getting wrong values. I got some 1's when there was no input. So I wrote a some code to teste inputs:

void setup() {
  Serial.begin(9600);
    for (int i=0; i <= 13; i++)
  {pinMode(i, INPUT);}
}

void loop() {
for (int i=0; i <= 13; i++)
  {
  int sensorVal = digitalRead(i);
  Serial.print(sensorVal);
  }
Serial.println();
delay(2500);
}

I expected to get only zeros, since the arduino has nothing connected on the inputs. But I'm getting weird values:

10000000000000
10000000000001
10000000000001
10000000000001
10000000000001
10000000000001
11000000000001
11000000000001
11000000000001
10000000000001
10000000000001
10000000000001
10000000000001
11000000000001
11000000000001
10000000000001
10000000000001

Do I have a faulty arduino, or I'm missing something?[/code]

I found out what seams to be the problem

You are trying to use pins 0 and 1 as the Serial port AND as input pins. That hasn't worked for anyone else. What makes you think you are special?