I have to read as input a signal that is composed by:
-pause time signal (about six seconds) = output high
-start transmission signal (2000 microseconds, all value are approximate) = output low
-data 72 low signals that are: 90 microseconds for 0 and 200 microseconds for 1
I've tried with pulseIn() function and I succesfully found the start transmission,
I've also found some data signal but arduino digital readings are too slow to grab all the 72 signals
There is a way to "accelerate" arduino readings?
I need approximately a 20 microseconds resolution,
I've also tried SoftwareSerial for reading that signal. i know there's a signal every 316uS but i cannot handle it as serial,, the problem is the baudrate....
There's a way to have the serial speed for digital reading?
Maybe some libraries...
That is actually not a very fast signal and it should be easy for you to capture all the pulses and timings.
Post the code you have so far and perhaps someone will see what the real problem is. Use code tags to properly format your code.
int in = 2;
int i=0;
void setup() {
Serial.begin(57600);
pinMode(in, INPUT);
}
void loop() {
i++;
int state = digitalRead(in);
Serial.print(i);
Serial.print(" HIGH ");
Serial.println(pulseIn(in,HIGH));
Serial.print(i);
Serial.print(" LOW ");
Serial.println(pulseIn(in,LOW));
delayMicroseconds(1); // delay in between reads for stability
}
It returns aproximately 11 reads every transmission, but the signal is the appended image:
first signal is the start signal,
then 64 short/long signal (8byte)
In the Arduino system Serial.print is relatively slow. You should read all your pulses and only print stuff when all of the input is finished.
What are you trying to get from the data? If you just want to get the pattern of highs and lows (similar to serial data) there is probably no need to use pulsein.
I would have some code to detect the start of transmission and then sample the data at a suitable rate. Again, digitalRead() is relatively slow and you may be better to use direct port manipulation Arduino Reference - Arduino Reference
I agree with Robin2. The printing is the real problem. Save the pulse timings in a array and print that later. My approach would be to use direct port manipulation to read the input pin, detect the transitions sequentially in a tight polling loop and use micros() to time the transitions. That would have a pulse timing resolution of roughly 4 microseconds.
The plot of the pulse train doesn't quite match your description. If the data are actually encoded in the length of the low pulses, I would expect the highs to have all the same length, but they do not appear to do so.
Maybe you could adapt this code to your needs. I knocked it up some time ago to read data from a weather sensor. It may not work fast enough for your signal unless you use direct port manipulation though.
// Unknown 433Mhz weather sensor decoder.
// __ ___ ___ ___
// | | | | | | |
// |_________| |______| |___| |
//
// | Sync | 1 | 0 |
// | 8320us | 4500us | 2530us
// Defines
#define allDataBits 42 // Number of data bits to expect
// isrFlags bit numbers
#define F_HAVE_DATA 1 // 0=Nothing in read buffer, 1=Data in read buffer
#define F_GOOD_DATA 2 // 0=Unverified data, 1=Verified (2 consecutive matching reads)
#define F_CARRY_BIT 3 // Bit used to carry over bit shift from one long to the other
#define F_STATE 7 // 0=Sync mode, 1=Data mode
// Constants
const unsigned long sync_MIN = 8120; // Minimum Sync time in micro seconds
const unsigned long sync_MAX = 8520;
const unsigned long bit1_MIN = 4300;
const unsigned long bit1_MAX = 4700;
const unsigned long bit0_MIN = 2330;
const unsigned long bit0_MAX = 2730;
const unsigned long glitch_Length = 300; // Anything below this value is a glitch and will be ignored.
// Interrupt variables
unsigned long fall_Time = 0; // Placeholder for microsecond time when last falling edge occured.
unsigned long rise_Time = 0; // Placeholder for microsecond time when last rising edge occured.
byte bit_Count = 0; // Bit counter for received bits.
unsigned long build_Buffer[] = {0,0}; // Placeholder last data packet being received.
volatile unsigned long read_Buffer[] = {0,0}; // Placeholder last full data packet read.
volatile byte isrFlags = 0; // Various flag bits
void PinChangeISR0(){ // Pin 2 (Interrupt 0) service routine
unsigned long Time = micros(); // Get current time
if (digitalRead(2) == LOW) {
// Falling edge
if (Time > (rise_Time + glitch_Length)) {
// Not a glitch
Time = micros() - fall_Time; // Subtract last falling edge to get pulse time.
if (bitRead(build_Buffer[1],31) == 1)
bitSet(isrFlags, F_CARRY_BIT);
else
bitClear(isrFlags, F_CARRY_BIT);
if (bitRead(isrFlags, F_STATE) == 1) {
// Looking for Data
if ((Time > bit0_MIN) && (Time < bit0_MAX)) {
// 0 bit
build_Buffer[1] = build_Buffer[1] << 1;
build_Buffer[0] = build_Buffer[0] << 1;
if (bitRead(isrFlags,F_CARRY_BIT) == 1)
bitSet(build_Buffer[0],0);
bit_Count++;
}
else if ((Time > bit1_MIN) && (Time < bit1_MAX)) {
// 1 bit
build_Buffer[1] = build_Buffer[1] << 1;
bitSet(build_Buffer[1],0);
build_Buffer[0] = build_Buffer[0] << 1;
if (bitRead(isrFlags,F_CARRY_BIT) == 1)
bitSet(build_Buffer[0],0);
bit_Count++;
}
else {
// Not a 0 or 1 bit so restart data build and check if it's a sync?
bit_Count = 0;
build_Buffer[0] = 0;
build_Buffer[1] = 0;
bitClear(isrFlags, F_GOOD_DATA); // Signal data reads dont' match
bitClear(isrFlags, F_STATE); // Set looking for Sync mode
if ((Time > sync_MIN) && (Time < sync_MAX)) {
// Sync length okay
bitSet(isrFlags, F_STATE); // Set data mode
}
}
if (bit_Count >= allDataBits) {
// All bits arrived
bitClear(isrFlags, F_GOOD_DATA); // Assume data reads don't match
if (build_Buffer[0] == read_Buffer[0]) {
if (build_Buffer[1] == read_Buffer[1])
bitSet(isrFlags, F_GOOD_DATA); // Set data reads match
}
read_Buffer[0] = build_Buffer[0];
read_Buffer[1] = build_Buffer[1];
bitSet(isrFlags, F_HAVE_DATA); // Set data available
bitClear(isrFlags, F_STATE); // Set looking for Sync mode
digitalWrite(13,HIGH); // Used for debugging
build_Buffer[0] = 0;
build_Buffer[1] = 0;
bit_Count = 0;
}
}
else {
// Looking for sync
if ((Time > sync_MIN) && (Time < sync_MAX)) {
// Sync length okay
build_Buffer[0] = 0;
build_Buffer[1] = 0;
bit_Count = 0;
bitSet(isrFlags, F_STATE); // Set data mode
digitalWrite(13,LOW); // Used for debugging
}
}
fall_Time = micros(); // Store fall time
}
}
else {
// Rising edge
if (Time > (fall_Time + glitch_Length)) {
// Not a glitch
rise_Time = Time; // Store rise time
}
}
}
void setup() {
pinMode(13,OUTPUT); // Used for debugging
Serial.begin(9600);
pinMode(2,INPUT);
Serial.println(F("ISR Pin 2 Configured For Input."));
attachInterrupt(0,PinChangeISR0,CHANGE);
Serial.println(F("Pin 2 ISR Function Attached. Here we go."));
}
void loop() {
unsigned long myData0 = 0;
unsigned long myData1 = 0;
if (bitRead(isrFlags,F_GOOD_DATA) == 1) {
// We have at least 2 consecutive matching reads
myData0 = read_Buffer[0]; // Read the data spread over 2x 32 variables
myData1 = read_Buffer[1];
bitClear(isrFlags,F_HAVE_DATA); // Flag we have read the data
dec2binLong(myData0,10);
dec2binLong(myData1,32);
Serial.print(" - Battery=");
byte H = (myData1 >> 30) & 0x3; // Get Battery
Serial.print(H);
Serial.print(" Channel=");
H = (myData1 >> 28) & 0x3; // Get Channel
Serial.print(H);
Serial.print(" Temperature=");
byte ML = (myData1 >> 16) & 0xF0; // Get MMMM
H = (myData1 >> 24) & 0xF; // Get LLLL
ML = ML | H; // OR MMMM & LLLL nibbles together
H = (myData1 >> 16) & 0xF; // Get HHHH
int Temperature = (H << 8) | ML; // Combine HHHH MMMMLLLL
Temperature = Temperature -900; // Remove Constant offset
Serial.print(Temperature/10.0,1);
Serial.print("F Humidity=");
H = (myData1 >> 4) & 0xF0; // Get HHHH
ML = (myData1 >> 12) & 0xF; // Get LLLL
ML = ML | H; // OR HHHH & LLLL nibbles together
Serial.print(ML);
Serial.println("%");
}
delay(100);
}
void dec2binLong(unsigned long myNum, byte NumberOfBits) {
if (NumberOfBits <= 32){
myNum = myNum << (32 - NumberOfBits);
for (int i=0; i<NumberOfBits; i++) {
if (bitRead(myNum,31) == 1)
Serial.print("1");
else
Serial.print("0");
myNum = myNum << 1;
}
}
}
Thanks to all, i've solved simply by using an array and print it when it is full....
The rest of the code will be executed only when array is full (i've six seconds between each read)
That's the code that i have wrote to handle similiar signal (if somebody needs)
int in = 2;
int i=0;
unsigned long incomingTime[67];
int startComm=0;
unsigned long processingTime;
String incomingBit[65];
String incomingByteBIN[8];
byte incomingByteDEC[8];
boolean flagBit;
int checksum=0;
void setup() {
Serial.begin(115200);
pinMode(in, INPUT);
}
void loop() {
processingTime=pulseIn(in,HIGH,700);
if (processingTime > 500){
startComm=1;
}
if (startComm==1){
incomingTime[i]=processingTime;
i++;
}
if (i==67){
/*Unused code
int maximum=0;
int half=0;
for (int a=1; a<=67; a++){
if (incomingTime[a] > maximum){
maximum=incomingTime[a];
}
}
half = (maximum/2)+30;
*/
startComm=0;
i=0;
for (int k=1;k<=67;k++){
if (incomingTime[k] <= (100) ){
incomingBit[k]="0";
}
else{
if (incomingTime[k]<=(200)){
incomingBit[k]="1";
}
}
flagBit = 1;
}
}
if (flagBit==1){
for (int z=0;z<=7;z++){
incomingByteBIN[z]="";
}
flagBit=0;
Serial.println();
for (int j=1;j<=64;j++){
if (j<=8){
incomingByteBIN[0]= incomingByteBIN[0] += incomingBit[j];
}
if (j>8 && j<=16){
incomingByteBIN[1]=incomingByteBIN[1] += incomingBit[j];
}
if (j>16 && j<=24){
incomingByteBIN[2]=incomingByteBIN[2] += incomingBit[j];
}
if (j>24 && j<=32){
incomingByteBIN[3]=incomingByteBIN[3] += incomingBit[j];
}
if (j>32 && j<=40){
incomingByteBIN[4]=incomingByteBIN[4] += incomingBit[j];
}
if (j>40 && j<=48){
incomingByteBIN[5]=incomingByteBIN[5] += incomingBit[j];
}
if (j>48 && j<=56){
incomingByteBIN[6]=incomingByteBIN[6] += incomingBit[j];
}
if (j>56 && j<=64){
incomingByteBIN[7]=incomingByteBIN[7] += incomingBit[j];
}
}
checksum=0;
for (int z=0;z<=7;z++){
incomingByteDEC[z]=(incomingByteBIN[z]).toInt();
Serial.print(incomingByteDEC[z]);
Serial.print(":");
if (z<7){
checksum=checksum+incomingByteDEC[z];
}
}
//Decoding function under development
double current_adc = (incomingByteDEC[4] * 256) + incomingByteDEC[5];
double result = (220 * current_adc) / ((double) 32768 / (double) pow(2,incomingByteDEC[6]));
Serial.print(" Watt: ");
Serial.print(result);
Serial.println();
}
}