Reading data at 10 Khz rate

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;
}

Thanks a lot sir it is working cann't express the joy of seeing it works in words Thanks thanks thanks and also my respect and gratitude to all Rob, Geoff , Mike without your help and suggestion it would have not been possible

Thanks to everybody for response will come back to you when stuck with another problem(i have very little knowledge so it is highly unlikely that i can say something anybody problem)

Thanks a lot Niladri

I think you'll be back soon because you don't have code that will sync with the data yet :)


Rob

This seemed like an interesting problem so I spent a little time working on some code because I think you are still a long way from having a real solution.

It’s a problem crying out for a state machine so here is my first pass

const int CLOCK_PIN     =     2;
const int DATA_PIN      =     4;
const int PACKET_BITS   =     128;
const int PREAMBLE_LEN  =    6;
const int DATA_LEN      =    ((PACKET_BITS / 4) - PREAMBLE_LEN);

enum {
    PRE_0,    PRE_1,    PRE_2,    PRE_3,    PRE_4,    PRE_5,    DATA
} states;    

byte     preamble [] = {0x0C,0x0A,0x0A,0x0C,0x01,0x0F};
char     hexAsciiVals[] = "0123456789ABCDEF";
byte     state = PRE_0;
byte     nibble;
int        nibble_count = 0;

void setup() {
  pinMode(CLOCK_PIN, INPUT);
  pinMode(DATA_PIN, INPUT);
  Serial.begin(115200);
}

void loop() {

    nibble = getNibble();
    nibble_count++;
    
    switch (state) {    
        case PRE_0:
            if (nibble_count > PREAMBLE_LEN + DATA_LEN) {
                // we've read 32 bytes and still not found a match 
                // for the preamble so skip a clock pulse
                while (digitalRead(CLOCK_PIN) == HIGH);
                while (digitalRead(CLOCK_PIN) == LOW);
                nibble_count = 0;
            } else {
                state = (nibble == preamble[0]) ? PRE_0 : PRE_1;
            }
            break;
        
        case PRE_1:
            state = (nibble == preamble[1]) ? PRE_0 : PRE_2;    
            break;
            
        case PRE_2:
            state = (nibble == preamble[2]) ? PRE_0 : PRE_3;
            break;

        case PRE_3:
            state = (nibble == preamble[3]) ? PRE_0 : PRE_4;
            break;

        case PRE_4:
            state = (nibble == preamble[4]) ? PRE_0 : PRE_5;
            break;
        
        case PRE_5:
            state = (nibble == preamble[5]) ? PRE_0 : DATA;
            break;
            
        case DATA:
            Serial.write (hexAsciiVals[nibble]);
            if (nibble_count == DATA_LEN) {
                // all done, start again
                state = PRE_0;
                nibble_count = 0;
            }
            break;
    }
}

byte getNibble() {

    byte val = 0;
    
    for (byte bit_count = 0; bit_count < 4; bit_count++) {
        while (digitalRead(CLOCK_PIN) == HIGH);
        while (digitalRead(CLOCK_PIN) == LOW);
        val <<= 1;
        val |= digitalRead(DATA_PIN); 
    }
    return (val &= 0x0F);
}

It compiles but I may have stuffed up some logic, hopefully not.

As the states are contiguous you could probably replace some of the switch() cases with a simple state++ but I think this allows for changes to be more easily implemented.


Rob

Yes you are absolutely right though its reads corrects value some times but once its looses its sync it does take lot of value to again com its actual position. So what could i do to make to once it looses its sync on next or in 2-3 iteration its sync again. :frowning: :frowning:

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



void setup()
{
  pinMode(pin2, INPUT);
   
  pinMode(pin4, INPUT);
  
  Serial.begin(2400);
}
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;
}

Just for curiosity can ISR(edge triggered) be used at that frequency

newbee_2:
Yes you are absolutely right though its reads corrects value some times but once its looses its sync it does take lot of value to again com its actual position. So what could i do to make to once it looses its sync on next or in 2-3 iteration its sync again. :frowning: :frowning:

Reading through Rob’s code, if it loses its way, it will/should pick up the next preamble characters so long as the 4-bit boundary is maintained. So if you’ve got out of sync by 1, 2 or 3 bits one way to potentially make it pick up the trail sooner is to construct a state machine looking for the pattern of bits of the preamble rather than the sequence of nibbles (which wouldn’t be found if you are no longer sampling nibbles at the correct bit boundary). Also, presuming there’s a bit on every high clock pulse I’m wondering if the marked line below, will mean the first ever bit in the stream is always lost which would throw it out of sync from the start?

byte getNibble() {

    byte val = 0;
    
    for (byte bit_count = 0; bit_count < 4; bit_count++) {
        while (digitalRead(CLOCK_PIN) == HIGH);  // <<< THIS LINE
        while (digitalRead(CLOCK_PIN) == LOW);
        val <<= 1;
        val |= digitalRead(DATA_PIN); 
    }
    return (val &= 0x0F);
}

You do say it works, so I presume I’m wrong on that point.

Geoff

It might get a bit tight Geoff, after getting a nibble you have ~100uS to get back to the getNibble() function. If you don't make it you are out of sync again. I'll have a think about the timing but it may be better to put that code inline, at least that will save a function call.

You do say it works, so I presume I'm wrong on that point.

I'm not sure newbee_2 is using my code.

One thing I/we didn't think of is that presumably the PC still needs to see the preamble as it doesn't know all this is happening. So after we get in sync we need to send those 6 bytes.


Rob

can ISR(edge triggered) be used at that frequency

Yes, and that may be a good way to go. But if we're worried about having enough time interrupts will make it worse.


Rob

Ok this code is most efficient so far once it goes out of Sync in 2-3 iteration it comes back but they are saying make it like sliding window and you keep on sliding 1 bit at a time until you found the match("CAAC1F") and when found send it reaming bits(128-24=104) and again start the process. Can it be done? Thanks and Regards Niladri

this code is most efficient so far

Which code are we talking about now?

2-3 iteration

What is an "iteration" in this context?

Can it be done?

I think that's what my example did but I haven't revisited it because I don't know if you have tried it or not.


Rob

The code on post 32.
Some time that code also looses its Sync but once it looses it comes back after 2-3 wrong value
No in that code you have checked only 32 byte and after you skip a pules but data stream is continuous so pulse skip might not possible

const int CLOCK_PIN     =     2;
const int DATA_PIN      =     4;
const int PACKET_BITS   =     128;
const int PREAMBLE_LEN  =    6;
const int DATA_LEN      =    ((PACKET_BITS / 4) - PREAMBLE_LEN);

enum {
    PRE_0,    PRE_1,    PRE_2,    PRE_3,    PRE_4,    PRE_5,    DATA
} states;    

byte     preamble [] = {0x0C,0x0A,0x0A,0x0C,0x01,0x0F};
char     hexAsciiVals[] = "0123456789ABCDEF";
byte     state = PRE_0;
byte     nibble;
int        nibble_count = 0;

void setup() {
  pinMode(CLOCK_PIN, INPUT);
  pinMode(DATA_PIN, INPUT);
  Serial.begin(9600);
}

void loop() {

    nibble = getNibble();
    nibble_count++;
    
    switch (state) {    
        case PRE_0:
            if (nibble_count > 32) { // I made this change for my own understanding
                // we've read 32 bytes and still not found a match 
                // for the preamble so skip a clock pulse
                while (digitalRead(CLOCK_PIN) == HIGH);
                while (digitalRead(CLOCK_PIN) == LOW);
                nibble_count = 0;
            } else {
                state = (nibble == preamble[0]) ? PRE_0 : PRE_1;
            }
            break;
        
        case PRE_1:
            state = (nibble == preamble[1]) ? PRE_0 : PRE_2;    
            break;
            
        case PRE_2:
            state = (nibble == preamble[2]) ? PRE_0 : PRE_3;
            break;

        case PRE_3:
            state = (nibble == preamble[3]) ? PRE_0 : PRE_4;
            break;

        case PRE_4:
            state = (nibble == preamble[4]) ? PRE_0 : PRE_5;
            break;
        
        case PRE_5:
            state = (nibble == preamble[5]) ? PRE_0 : DATA;
            break;
            
        case DATA:
            Serial.write (hexAsciiVals[nibble]);
            if (nibble_count == DATA_LEN) {
                // all done, start again
                state = PRE_0;
                nibble_count = 0;
            }
            break;
    }
}

byte getNibble() {

    byte val = 0;
    
    for (byte bit_count = 0; bit_count < 4; bit_count++) {
        while (digitalRead(CLOCK_PIN) == HIGH);
        
          while (digitalRead(CLOCK_PIN) == LOW);
        
          val <<= 1;
          val |= digitalRead(DATA_PIN);
        
          
    }
    return (val &= 0x0F);
}