 # Reading pulses (HIGH's and LOW's) from external device

Hi, i am trying to get the information being sent from a device which sends 28 bits, the first 14 is a bearing next 2 is zeroes next 10 is distance and finally last 2 are zeroes again. The pulse max volt is 2. I would like to read these pulses in order to send these information to pc. The cycle is 4,74msec of every 28 bits. Has anyone any idea which pin to use? Because i used a digital pin (even pin0), but i couldnt get proper reasaults. Thanks in advance.(I am an arduino beginner)

is each pulse 169.29 microseconds (4.74 mSec/28) long?

How do you know when the stream of bits starts?

I don’t know if this is accurate enough but it should be a start:

``````while (digitalRead(inputPin) == LOW)   // Wait for a rising edge
/* Do Nothing */ ;
unsigned long startTime = micros();
for (int bit = 0; bit < 48; bit++)
{
unsigned long bitTime = bit * 169.29;
while (micros() - startTime < bitTime)   // Wait for bit to arrive
/* Do Nothing */ ;
bits[bit] = digitalRead(inputPin);
}
``````

better skip halve a bit for the first bit or adapt the multiplication factor so one is not at the edge of the signal but in the middle.

here an version build upon John’s one.

Note: you may need to adjust the magic number 170 to get the timing compensated for the time the loop instructions - e.g. digitalRead() - take.

``````while (digitalRead(inputPin) == LOW)   // Wait for a rising edge
/* Do Nothing */ ;

unsigned long startTime = micros();
unsigned long bitTime = 50;                // skip ~halve a bit to be in the middle
for (int bit = 0; bit < 48; bit++)
{
while (micros() - startTime < bitTime)   // Wait for bit to arrive
/* Do Nothing */ ;
bits[bit] = digitalRead(inputPin);           // read the bit
bitTime += 170;                                 // update bittime (with an addition iso float multiplication)
}
``````

Your task is not unlike that of a software serial uart function. But instead of converting 8 serial bits frame into single byte size characters, you have to convert the whole serial bit stream on the run. First you have to determine a valid start of the frame, then do mid bit sampling on the bit stream to extract the ones and zeros, and finally validate the end of frame markers, the two final zero bits, then get ready for the next valid frame start . Not an easy task but doable if you stick to it.

Lefty

Thank you guys. I am going to try the code at the lab tomorrow. I'll lwt you know of the resaults. It is of great importance to finally read these bits.

aegeandp:
Thank you guys. I am going to try the code at the lab tomorrow. I’ll lwt you know of the resaults. It is of great importance to finally read these bits.

Do you have any more details about the data stream? Is it documented somewhere?

Ok this is the situation:
There are two wires coming from the device:
The first is clock: 20msec low - 20msec high , pulse has 3 volt(high)
the second holds the 28 bit information i want to retreive:
when the clock pulse turns to low the 28 bit tranmission begins.
each bit has a 156?sec duration(3.2 volt for high pulse). All the bits together have 4,37msec duration (28/4.37msec=156?sec)
The arduino doesnot recognize the high pulses (maybe its the voltage).
|____________________________________|-------------------------------------------------| (CLOCK)

LOW HIGH=3Volt
← 20msec -><- 20msec →

|---------__| (BINARY(28 bits): HIGH=3,2VOLT)
← 4,37msec →

the first 14 bits is INFORMATION “a” next 2 bits are 0 (zero) next 10 bits is INFORMATION “b” and next 2 bits are high.
So i want to retreive info “a” & “b”
Thanks in advance!

``````// Wait till the clock goes from HIGH to LOW:
while (digitalRead(ClockPin) == LOW)   // Wait for the clock to be HIGH
/* Do Nothing */ ;
while (digitalRead(ClockPin) == HIGH)   // Wait for the clock to go LOW
/* Do Nothing */ ;

delayMicroseconds(156/2);
for (int bit = 0; bit < 48; bit++)
{
bits[bit] = digitalRead(inputPin);
delayMicroseconds(156);
}
``````

Since digitalRead() takes a few microseconds you will probably have to reduce the delay between reads to something less than 156. You can put timing code around the loop and adjust the timing until the total loop take 4370 microseconds.

``````unsigned long start = micros();
for (int bit = 0; bit < 48; bit++)
{
bits[bit] = digitalRead(inputPin);
delayMicroseconds(156);
}
unsigned long stop = micros();
Serial.print(stop-start);   // Adjust the delay until the loop time is as close as you can get to 4370 microseconds.
``````

The arduino does not recognize the high pulses (maybe its the voltage).

Well three volts is marginal, but should still be seen as a valid high state. You are of course wiring a ground wire between the arduino and the source of these two signals? It is required.

Lefty

retrolefty:

The arduino does not recognize the high pulses (maybe its the voltage).

Well three volts is marginal, but should still be seen as a valid high state. You are of course wiring a ground wire between the arduino and the source of these two signals? It is required.

Lefty

For a less marginal signal you can power the Arduino with 4V instead of 5V. That would put the HIGH signal level at 2.4V instead of 3.0V.

Thank you very much i will try the code at the lab!

Problem SOLVED. Thank u very much. The code needed minor changes but it worked.

Can you post the final working code? Could be useful for future reference.