Reading data at 10 Khz rate

Hi guys
Can arduino Uno read digital data of 10 KHz frequency?
Thanks in advance
Niladri.

Hi Niladri

Do you need a serial connection that's 10,000 baud? Then yes, that's possible with Arduino Uno.

Geoff

What form is this data in? Is it serial or parallel?
The arduino has a 16MHz processor so 10KHz is slow, however what are you going to do with it! There is not much room to store very much data, less than a few mS at that rate.

Thanks for the reply
Actually i need to read a clock of 10 khz and each positive going pulse i need to read data. I have already done using NI LabVIEW and its DAQ card but i want a cheaper replacement so was thinking can i use arduino uno or not?
Is it possible??
Thanks in advance
Niladri.

Yes this sounds like an SPI data protocol, look up how to do that.

Data is parallel and i will send the data to the pc with the help of file write i will store it in the pc(A cheap DAQ at 10 KHz )

No sir it is not SPI protocol it is more of a Simple Discrete to Serial Converter at 10 KHz clock speed. I am aware of SPI protocol. I have already implemented SPI protocol in arduino.

Ok we are in blood out of a stone mode. How many bits parallel?
There is a complication in that there is not a free 8 bit port on the arduino so you would have to read them in prices and put them together into bytes to send serially.
Will you need a protocol , or can you just stream it out?

Thanks everyone for their replies
it is 8 bits and no protocol only serial data

i have written this code but it is not giving me the hex data which i have given as input.
Any suggestion?
Niladri

const int pin1 = 2; // the pin where clock will be taken
const int pin2 = 4; // the pin for data input
int count;


void setup() 
{
  //  initialize the button pin as a input:
  pinMode(pin1, INPUT);
  //  initialize the button pin as a input:
  pinMode(pin2, INPUT);
  //  Initializing for serial communication
  Serial.begin(9600);
}
void loop()
{
  int clock = digitalRead(pin1); // Reading the clock 
   
  if (clock == HIGH) // At each raising edge data should be taken 
  {
    int data = digitalRead(pin2); // when a raising edge comes read the data 
    count++;
    if(count%4 == 0)
        Serial.print(data, HEX);// Read the data on serial moniter to check logic is right or not
   
  }
}

Hi,

You mentioned the data was parallel earlier, but here you're only allowing for one data line, so I'll presume you meant the data was purely serial.

Every time loop() is run, the variable data is recreated losing the previous information. So while I can see your intention is to read the data line for 4 pulses then output, the only thing you'll ever have to output is the value of the most recent digitalRead (either 0 or 1 being LOW or HIGH) stored in the variable data. So if you're going to construct the data variable a bit at a time, that variable needs to have a global scope, same as your count variable, and store the bit that you read in the right position within it (via bitset() maybe, or some bitwise math regardless) each iteration of loop() then discard the content on the 4th pass after printing. Hope that makes sense.

Also while your comment suggests this next test is for a rising edge...
if (clock == HIGH) // At each raising edge data should be takenin actual case there's nothing to stop it reading the data line multiple times for any one HIGH pulse of the clock, presuming loop() executes fast enough. Also, of course there's nothing there to stop it missing out on data if your loop() takes too long, but that's unlikely in this scenario I think. If you truly need it to be on the rising edge, you might consider implementing this using interrupts; alternatively use an additional check that the clock line is HIGH, but last time through was LOW, and only act when that's the case.

Cheers ! Geoff

How about you verify the number of bits you need. According to your code it's 4.

There are faults in your code as strykeroz has commented on, but for a start to get 4 bits you need to accumulate the results of 4 digitalRead()s, for example

loop () {
    static byte val  = 0b00001000;

    if (rising_edge_on_clock_pin) {   // you figure out how to detect this
       val <<= 1;
       val |= digitalRead(pin2); 
       if(val | 0x80) {   // flag bit has reached the top of the byte so we've done 4 iterations
           Serial.print(val & 0x7F, HEX);
           val = 0b00001000;
         }
    }
}

Rob

Yes Rob but the big thing he is mixed up about is if the data is serial or parallel. He has said in one post that is was parallel so he needs to read more than one pin and amalgamates the results into one byte before sending it. This might be best doing two reads direct from two ports and oring them together. Choice of the right pins to wire the data to is crucial to making this efficient.

Sorry for initially mentioning that the data is parallel but now it has converted to serial. I have tried using everybody idea(especially Rob) but yet no fruitful result

const int pin2 = 2;
const int pin4 = 4;
int clock;
int clock1;

void setup()
{
  pinMode(pin2, INPUT);
   
  pinMode(pin4, INPUT);
  
  Serial.begin(9600);
}
void loop()
{
  static byte val  = 0b00001000;

    clock = digitalRead(pin2);
    if ((clock == HIGH) && (clock1 == LOW) {   
       val <<= 1;
       val |= digitalRead(pin2); 
       if(val | 0x80) {   // flag bit has reached the top of the byte so we've done 4 iterations
           Serial.print(val & 0x7F, HEX);
           val = 0b00001000;
         }
      clock1 = digitalRead(pin2);   
    }
}

Hi

Two obvious things I think to look at - firstly clock1 isn't initialised, so first pass through it won't have a reliable value. You can fix that in your declaration:

int clock1 = 0;

And the other part is you don't want to set clock1 at the end of the loop to whatever the digital pin value is, but rather what clock was. Like this:

      clock1 = digitalRead(pin2);
// becomes
      clock1 = clock;

Just two thoughts to start you off :slight_smile:

Geoff

strykeroz:
Hi

Two obvious things I think to look at - firstly clock1 isn't initialised, so first pass through it won't have a reliable value. You can fix that in your declaration:

int clock1 = 0;

Given that clock1 is a global variable, the compiler/runtime system guarantees that it will be 0 when the program starts up. This is required by the ISO C and C++ standards. Now, if clock1 were an auto variable, then yes, you would need the initializer.

MichaelMeissner:
Given that clock1 is a global variable, the compiler/runtime system guarantees that it will be 0 when the program starts up. This is required by the ISO C and C++ standards. Now, if clock1 were an auto variable, then yes, you would need the initializer.

That's good to know - thanks. Scratch that one then.

You cannot do a serial.print() in the middle of collecting data at 10kHz. You should collect everything then print the results. I probably should not have put that in there but it depends on how many bits in total are you grabbing. I wrote that for a one-off grab of 4 bits, how many are you grabbing?

Also this

clock1 = digitalRead(pin2);

should be changed to

clock1 = clock;

as has been mentioned and I think it should be moved outside the if block. So loop() looks like this

void loop()
{
  static byte val  = 0b00001000;

    clock = digitalRead(pin2);
    if ((clock == HIGH) && (clock1 == LOW) {   
       val <<= 1;
       val |= digitalRead(pin2); 
       if(val | 0x80) {   // flag bit has reached the top of the byte so we've done 4 iterations
           Serial.print(val & 0x7F, HEX);
           val = 0b00001000;
         }
     }
     clock1 = clock;   
}

Still only good for one sample though because of the serial.print()

What is this data and what is it coming from? At that speed you won't be able to keep up unless there's a break at some point to allow you time to do something with the data.


Rob

This is a major problem

  Serial.begin(9600);

At this speed you can only output 960 chars per second. You are printing hex, that is 2 chars per byte so that is twenty times too slow.

Plus other stuff mentioned already.

Many thanks to everybody for their response
the Data is coming from a decoding device and it is continuously running for 1-2 hours
I just need to send those data to PC as like serial data because pc cannot read discrete input.
Thanks in advance
Niladri