Reading data at 10 Khz rate

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

You have to up the serial port bit rate as Mike said, use 115200 and get the serial over with fast.

But I suspect that you will have another problem. What is the format of this data? Is each 4 bits a unique value or just part of a continuous bit stream. If it's a unique value you have to sync with the nibbles and with SPI that's all but impossible without another input or a longish time delay between nibbles.

Before working any more with code we need to know the exact nature of the incoming bits and the timing between the groups of four.

Data is coming from a decoding device

Data sheet?


Rob

Decoding device is under process(We are building our own homemade BCH decoder)
You can say it is filter tuned for 5.5 khz and 3.125 khz and it generates pulses and clock recovery system recover 10 khz clock now output from the 3.125 khz is passed through not gate to get stream of 128 bits(0 and 1) now each positive edge we need to read the value and each nibble we need convert to serial data and send it to pc. AS i said before it is like data acquisition system which can sample at 10 khz rate discrete input
If you have any other inquiry please let me know
Thanks in advance
Niladri

Ok,

  1. If there's 128 bits why do you need to grab them in nibbles.
  2. Is there any space/extra time between the nibbles?
  3. Is there any space/extra time between the 128-bit packets?
  4. What is the format of each nibble?
  5. Is there any way to detect the start/end of a 128-bit packet?

All this is leading to how do you sync with the data stream? If there is no spaces between nibbles and/or packets it is well nigh impossible to sync if you get out of whack.

EDIT: #5 added.


Rob

No first 24 bit will be CAAC1F(in HEX) if it is then receive next 96 bits otherwise slide to next bit until it matches the string but the string matching is done on a PC where LabVIEW software is running so my job is to silde it until i get send all 96 bits command from labview

And this code is somewhat working can you take a look at it.

const int pin2 = 2;
const int pin4 = 4;
int clock;
int clock1;
int val1;
int val2;
int val3;
int val4;
int val5;
int val6;
int val7;
int val8;
byte value =0000000;

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

    clock = digitalRead(pin2);
    if ((clock == HIGH) & (clock1 == LOW)) {   
       val <<= 1;
       val1 = digitalRead(pin4);
       val2 = digitalRead(pin4);
       val3 = digitalRead(pin4);
       val4 = digitalRead(pin4);
       val5 = digitalRead(pin4);
       val6 = digitalRead(pin4);
       val7 = digitalRead(pin4);
       val8 = digitalRead(pin4);
             if(val | 0x80) {   // flag bit has reached the top of the byte so we've done 8 iterations
           
           value=(value | (val1<<7));
           value=(value | (val2<<6));
           value=(value | (val3<<5));
           value=(value | (val4<<4));
           value=(value | (val5<<3));
           value=(value | (val6<<2));
           value=(value | (val7<<1));
           value=(value | (val8<<0));
           
           
           
           Serial.print(value & 0xFF, HEX);
           val = 0b00000001;
         }
         
    }
    clock1= clock;
}

And for your questions

  1. I need to send them as hex format for labview understanding
  2. No
  3. No
  4. HEX
  5. Keep on sending that Data till i receive a command from pc send next 96 bits of data that data also need to in HEX format fro labview understanding.
    Thanks in Advance
    Niladri

Sorry for that last code

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

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

    clock = digitalRead(pin2);
    if ((clock == HIGH) && (clock1 == LOW)) {   
       val <<= 1;

         val |= digitalRead(pin4);
             if(val | 0x80) {   // flag bit has reached the top of the byte so we've done 8 iterations
           

           
                      
           Serial.print(val & 0x7F, HEX);
           Serial.println();
           val = 0b00000001;
         }
    
    }
    clock1= clock;
}

newbee_2:
No first 24 bit will be CAAC1F(in HEX) if it is then receive next 96 bits otherwise slide to next bit until it matches the string but the string matching is done on a PC where LabVIEW software is running so my job is to silde it until i get send all 96 bits command from labview

And this code is somewhat working can you take a look at it.
...
And for your questions

  1. I need to send them as hex format for labview understanding
  2. No
  3. No
  4. HEX
  5. Keep on sending that Data till i receive a command from pc send next 96 bits of data that data also need to in HEX format fro labview understanding.
    Thanks in Advance
    Niladri

If I'm understanding you correctly, until you get a CAAC1F pattern match of the fixed pre-amble for the next frame/packet you won't know the bit boundary to start your 4-bit values on. Since that's the information you can use to synchronise your serial comms you will need to do the pattern matching on your Arduino rather than the PC or you'll not be guaranteed to be sending data that's aligned to the correct 4 bit boundaries. You can encode any arbitrary 4 bit pattern as hex and send it to the PC, but unless it's conforming to the correct 4-bit boundary your data will be meaningless.

If you know the CAAC1F pattern will be the preamble to every 128 bit data frame received, you can also use this as a mechanism to partially validate the most recent data received (ie once you've received 96 bits the next received data must be CAAC1F, or that previous data buffer is invalid).

Geoff

Sorry for that last code

Thank goodness, I was getting worried.

So as I understand it you keep feeding bytes (with the sampled nibbles in the lower 4 bits) to the PC, the PC reads 32 ASCII HEX chars, if it doesn't see 'C','A','A','C','1','F' after 32 bytes it tells you to move a bit and the whole process starts again. At some point the start sequence is found and you are off and racing.

I think you should do this on behalf of the PC because I doubt there is enough time to get the command from the PC, you only have 100nS and a PC can't do anything reliably in that time.


Rob

Through another arduino i am feeding 0x0F but in other arduino(receiver) i am reading all kind of junk values but not 0x0F what could be the mistake on my part

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



void setup()
{
  pinMode(pin2, INPUT);
   
  pinMode(pin4, INPUT);
  
  Serial.begin(2400);
}
void loop()
{
  static byte val  = 0b00000001;
  static byte value = 0b00000000;

    clock = digitalRead(pin2);
    if ((clock == HIGH) && (clock1 == LOW)) {   
       val <<= 1;

         value |= digitalRead(pin4);
         value <<= 1;
             if(val | 0x80) {   // flag bit has reached the top of the byte so we've done 8 iterations
           

           
                      
           Serial.print(value, HEX);
           Serial.println();
           val = 0b00000001;
          // value = 0b00000000;
          
         }
    
   
    }
    clock1= clock;
}

Thanks in advance
Niladri

newbee_2:
Through another arduino i am feeding 0x0F but in other arduino(receiver) i am reading all kind of junk values but not 0x0F what could be the mistake on my part

if(val | 0x80) {   // flag bit has reached the top of the byte so we've done 8 iterations

This doesn't do what you think it does, since the '|' operator is an OR, and the if statement will always be true. What you want is '&' which is an AND. I.e.:

if (val & 0x80) {

Now personally, I tend to prefer writing the above expression as:

if ((val & 0x80) != 0) {

You have mixed up the logic in that you should do the shift of value before doing the read and not after.

I would make 'val' a simple counter (and call it a more meaningful name). Something like:

void loop()
{
     static byte num_bits  = 0;
     static byte value = 0;

     clock = digitalRead(pin2);
     if ((clock == HIGH) && (clock1 == LOW))
        {   
            value = (value << 1) | digitalRead (pin4);
            if (++num_bits >= 8)                          // have we done 8 iterations?  If so print it out
                {
                     Serial.print(value, HEX);
                     Serial.println();
                     num_bits = 0;
                    value = 0;
                }
        }

    clock1= clock;
}