Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 04:42 27 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Serial communications

     Page 1 of 2    
Author Message
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1676
Posted: 08:31pm 25 Jan 2021
Copy link to clipboard 
Print this post

I'm trying to write code to read a sensor that sends data by serial at 9600 baud but I don't understand some things.
I've looked on here and searched Google but was not able to find anything that explained it in simple words I could understand

The format of the data I'm trying to decode is  










If I'm right then shouldn't character 31 start with BM? but it doesn't, it changes

This is what it's decoding




I'm trying to understand properly so I don't have to keep asking for help

This is also getting really frustrating having to take pictures of what I want to say so I can post it as the forum keeps saying it contains illegal ascii characters even when none of the ones I use are over 127 most times
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5903
Posted: 09:30pm 25 Jan 2021
Copy link to clipboard 
Print this post

For the checksum, add all the individual bytes together then take the lower 16 bits of the result.

It might help if you tell us what the sensor is so we can look at the data sheet.

Jim
VK7JH
MMedit   MMBasic Help
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5903
Posted: 05:05am 26 Jan 2021
Copy link to clipboard 
Print this post

This might be what you are after but without and datasheets, I am guessing.
 OPTION EXPLICIT
 OPTION DEFAULT NONE
 
 dim receivedData$ ' this is the string we received
 dim integer info(13) ' this is an array that will contain the 13 values we are looking for
   



sub getStuff receivedData$
 local integer tempData(32), n, datalength,checksum, check_high, check_low
 ' copy the string data into a numeric array
 for n = 1 to len(receivedData$)
   tempData(n) = asc(mid$(receivedData$,n,1))
 next n
 ' check to see if the starting values are "BM"
 if tempData(1) = asc("B") and tempData(2) = asc("M") then print "OK so far"
 ' the next two bytes tell us how long the data packet is. It should alwas be = 28 (2*13 + 2)
 dataLength = tempData(3)*256+tempData(4) ' tempData(3) should be 0 and tempData(4) = 28
 if dataLength = 28 then print "Still looks good"
 ' now we do a checksum by adding all the bytes and compare them with the checksum that was sent
 for n = 1 to 30
   checksum = checksum + tempData(n)
 next n
 check_low = checksum and 255
 check_high = (checksum /256) and 255
 if check_high = tempData(31) and if check_low = tempData(32) then print "check sum agrees!!!"
 ' if everything has gone well, it is safe to believe the data
 ' now we combine the high and low bytes for each of the 13 values
 for n = 1 to 13
   info(n) = tempData(n*2+3)*256+tempData(n*2+4)
 next n
 ' print the results
 for n = 1 to 13
   print info(n);",";
 next n
 print
end sub


Receive the data and send it to the SUB.

Jim
VK7JH
MMedit   MMBasic Help
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1676
Posted: 02:41pm 26 Jan 2021
Copy link to clipboard 
Print this post

Thanks Jim but I couldn't get it working, even after removing the if after the and if check_low

This seems to work but I'm not certain it's returning the correct values
I can't figure out how to get the Checksum calculated

I know it's probably extremely messy compared to what people who know what they are doing would produce and needs tidying up.

Its the PMS5003 air quality sensor Datasheet

OPTION EXPLICIT
OPTION DEFAULT NONE
DIM a$,b$
DIM as Integer c,d,e,f,g,h,i,j,k,l,m,n,o,p,particles_03um2,particles_05um2
DIM as Integer particles_10um2,particles_25um2,particles_50um2,particles_100um2
Open "COM1:9600" As #1

Do
a$ = INPUT$(1,#1)
b$ = b$ + a$
IF Len(b$) = 32 Then  ' valid data packets contain 32 characters
decode
b$ = ""
End IF
Loop

sub decode
IF left$(b$,2) = "BM" then ' Only proceed if probable Valid data is received
c = asc(mid$(b$,3)) 'Should be 0
d = asc(mid$(b$,4)) 'Should be 28
if c + d = 28 then ' data length is correct we probably have valid data
'do checksum here from asc(mid$(b$,31)) and asc(mid$(b$,32))  
'IF CHECKSUM = PREVIOUS CHECKSUM DISREGARD READING WE ONLY WANT DATA WITHOUT 2 CONSECUTIVE CHECKSUMS because unit sends data every second but only updates the readings every 2.3 seconds therefore we only want new data to display
'Only need values from Data7 high to Data12 low
e = asc(mid$(b$,17)) 'Data7 high
f = asc(mid$(b$,18)) 'Data 7 low
g = asc(mid$(b$,19)) 'Data 8 high
h = asc(mid$(b$,20)) 'Data 8 low
i = asc(mid$(b$,21)) 'Data 9 high
j = asc(mid$(b$,22)) 'Data 9 low
k = asc(mid$(b$,23)) 'Data 10 high
l = asc(mid$(b$,24)) 'Data 10 low
m = asc(mid$(b$,25)) 'Data 11 high
n = asc(mid$(b$,26)) 'Data 11 low
o = asc(mid$(b$,27)) 'Data 12 high
p = asc(mid$(b$,28)) 'Data 12 low
print e,f,g,h,i,j,k,l,m,n,o,p ' print all values to check
particles_03um2 = e + f  'value  I'm **ASSUMING** we add the values?
particles_05um2 = g + h  'value
particles_10um2 = i + j  'value
particles_25um2 = k + l  'value
particles_50um2 = m + n  'value
particles_100um2 = o + p 'value
print "Particles > 0.3um / 0.1L air: " STR$(particles_03um2)
print "Particles > 0.5um / 0.1L air: " STR$(particles_05um2)
print "Particles > 1.0um / 0.1L air: " STR$(particles_10um2)
print "Particles > 2.5um / 0.1L air: " STR$(particles_25um2)
print "Particles > 5.0um / 0.1L air: " STR$(particles_50um2)
print "Particles > 10.0 um / 0.1L air: " STR$(particles_100um2)
END IF
END IF
END SUB


I found this on how to calculate the checksum but I don't understand it



Also this
  Quote  byte readchar;
int recieveSum = 0;
int checkSum = 0;
int counter = 0;

 readchar = Serial1.read();
 if (readchar == 0x42) {
   Serial.println();
   recieveSum = 0;
   counter = 0;
 }
 if (readchar != 0xFF) Serial.print(readchar, HEX); //0xff occurs between frames and doesn't impact sums
 //Serial.print(readchar, HEX);
 if (counter < 30) recieveSum = recieveSum + readchar;
 if (counter == 30) checkSum = readchar;
 if (counter == 31) {
   checkSum = (checkSum << 8) + readchar;
   Serial.print(" CheckSum: "); Serial.print(recieveSum); Serial.print(" "); Serial.print(checkSum);
 }
 counter++;
 Serial.print(" ");
 delay(10);
}

Edited 2021-01-27 00:42 by lew247
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5903
Posted: 08:37pm 26 Jan 2021
Copy link to clipboard 
Print this post

I don't have the same type of sensor so you will have to give me something to work with
 OPTION EXPLICIT
 OPTION DEFAULT NONE
 DIM a$,b$
 DIM as Integer c
 Open "COM1:9600" As #1
 
 Do
   a$ = INPUT$(1,#1)
   b$ = b$ + a$
   IF Len(b$) = 32 Then  ' valid data packets contain 32 characters
     decode
     b$ = ""
   End IF
 Loop
 
sub decode
 IF left$(b$,2) = "BM" then ' Only proceed if probable Valid data is received
   for c = 1 to 32
     print asc(mid$(b$,c))
   next c
 endif
end sub

That will print out the 32 values received.
Give me a few sets.

Regarding the readings, a PM10 includes all particles less than 10 so it should already include the PM2.5 reading as well.

Have a read of this thread. Its about a different sensor but might help you understand them.
https://www.thebackshed.com/forum/ViewTopic.php?TID=11922&PID=143341#143341#143335
VK7JH
MMedit   MMBasic Help
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5903
Posted: 09:11pm 26 Jan 2021
Copy link to clipboard 
Print this post

If you have trouble getting the data, it might need to be synchronized to the start of the data stream.
If you start reading halfway through, you will never see 'BM' at the start.
This change is one way to bring the data stream into alignment.
 OPTION EXPLICIT
 OPTION DEFAULT NONE
 DIM a$,b$
 DIM as Integer c
 Open "COM1:9600" As #1
 
 Do
   a$ = INPUT$(1,#1)
   b$ = b$ + a$
   if len(b$) > 2 and left$(b$) <>"BM" then b$ = mid$(b$,2) ' synchronise the data stream
   IF Len(b$) = 32 Then  ' valid data packets contain 32 characters
     decode
     b$ = ""
   End IF
 Loop
 
sub decode
 IF left$(b$,2) = "BM" then ' Only proceed if probable Valid data is received
   for c = 1 to 32
     print asc(mid$(b$,c))
   next c
 endif
end sub

VK7JH
MMedit   MMBasic Help
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1676
Posted: 09:39pm 26 Jan 2021
Copy link to clipboard 
Print this post

  TassyJim said  I don't have the same type of sensor so you will have to give me something to work with

No problem reading the data, and it's confirming the first 2 bytes are correct
My issue is
it has 32 Bytes and each one of the ones I need consist of 16 bits 8 high and 8 low
I don't know if I#m meant to add the ascii values for the high and low bits to get the correct data, or what to do with it

for example below offset 12 which is Data 26 (16 bit)
Do I simple add the 8 upper and 8 lower bits together to get the byte value?
it's ascii values received if that helps

Also I really cannot get how to generate the checksum






As well as checksum, in binary format (its fairly easy to parse the binary format, but it doesn't come out as pure readable ascii text)
Adafruit have a tutorial here but it doesn't tell me in plain english what I need to know
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3015
Posted: 10:04pm 26 Jan 2021
Copy link to clipboard 
Print this post

You have to add +all+ bytes--30 in total--2 start bytes, 2 frame bytes, 26 data bytes.
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5903
Posted: 10:57pm 26 Jan 2021
Copy link to clipboard 
Print this post

You have to compare your calculated checksum with the devices checksum

for n = 1 to 30
  checksum = checksum + asc(mid$(b$,n))
next n

checksum_sent = asc(mid$(b$,31))*256 + asc(mid$(b$,32))

if checksum = checksum_sent then print "Yippee!!!!"


to get your values, you multiply the high byte by 256 and add the low byte.
VK7JH
MMedit   MMBasic Help
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5903
Posted: 02:28am 27 Jan 2021
Copy link to clipboard 
Print this post

I took one of the strings shown in your first photo and reconstructed the string.
^@ is zero and ^\ is 28
The rest are as expected ^B = 2, ^D = 4 etc.
I didn't try and guess what some of the >128 characters in the first string are.
(It would have been easier with some sample data)

In Australia, we use PM2.5 and PM10 so I looked it them. Both were 4 which is reasonable for indoors.
I haven't studied the smaller particle sizes so will not make any comment on those values.

By reading the string from DATA statements instead of the serial port, this is what I ended up with.
There is a difference of 256 between the check-sums. 256 is interesting and I would like to see more packets to see if that is a constant error/difference.

 OPTION EXPLICIT
 OPTION DEFAULT NONE
 DIM a$,b$
 dim integer cs, css
 DIM as Integer c,d,e,f,g,h,i,j,k,l,m,n,o,p,particles_03um2,particles_05um2
 DIM as Integer particles_10um2,particles_25um2,particles_50um2,particles_100um2
 
 '  Open "COM1:9600" As #1
 
 '  Do
 '    a$ = INPUT$(1,#1)
 '    b$ = b$ + a$
 '        if len(b$) > 2 and left$(b$) <>"BM" then b$ = mid$(b$,2) ' synchronise the data stream
 '    IF Len(b$) = 32 Then  ' valid data packets contain 32 characters
 '      decode
 '      b$ = ""
 '    End IF
 '  Loop
 
 
 ' sample data taken from image ^@ = 0 and ^\ = 28
 for n = 1 to 32
   read p
   b$ = b$+chr$(p)
 next n
 
 decode
 print
 
 print "PM2.5 = ";asc(mid$(b$,7,1))*256+asc(mid$(b$,8,1))
 print "PM10  = ";asc(mid$(b$,9,1))*256+asc(mid$(b$,10,1))
end
 
sub decode
 IF left$(b$,2) = "BM" then ' Only proceed if probable Valid data is received
   c = asc(mid$(b$,3)) 'Should be 0
   d = asc(mid$(b$,4)) 'Should be 28
   if c*256 + d = 28 then ' data length is correct we probably have valid data
     css =asc(mid$(b$,31,1))*256+asc(mid$(b$,32,1))
     print "supplied check sum = ";css
     for n = 1 to 30
       cs = cs + asc(mid$(b$,n,1))
     next n
     print "calculated check sum = ";cs
     print "difference = ";cs-css
     'do checksum here from asc(mid$(b$,31)) and asc(mid$(b$,32))
     'IF CHECKSUM = PREVIOUS CHECKSUM DISREGARD READING WE ONLY WANT DATA WITHOUT 2 CONSECUTIVE CHECKSUMS because unit sends data every second but only updates the readings every 2.3 seconds therefore we only want new data to display
     'Only need values from Data7 high to Data12 low
     e = asc(mid$(b$,17)) 'Data7 high
     f = asc(mid$(b$,18)) 'Data 7 low
     g = asc(mid$(b$,19)) 'Data 8 high
     h = asc(mid$(b$,20)) 'Data 8 low
     i = asc(mid$(b$,21)) 'Data 9 high
     j = asc(mid$(b$,22)) 'Data 9 low
     k = asc(mid$(b$,23)) 'Data 10 high
     l = asc(mid$(b$,24)) 'Data 10 low
     m = asc(mid$(b$,25)) 'Data 11 high
     n = asc(mid$(b$,26)) 'Data 11 low
     o = asc(mid$(b$,27)) 'Data 12 high
     p = asc(mid$(b$,28)) 'Data 12 low
     print e,f,g,h,i,j,k,l,m,n,o,p ' print all values to check
     particles_03um2 = e*256 + f  'value  I'm **ASSUMING** we add the values?
     particles_05um2 = g*256 + h  'value
     particles_10um2 = i*256 + j  'value
     particles_25um2 = k*256 + l  'value
     particles_50um2 = m*256 + n  'value
     particles_100um2 = o*256 + p 'value
     print "Particles > 0.3um / 0.1L air: " STR$(particles_03um2)
     print "Particles > 0.5um / 0.1L air: " STR$(particles_05um2)
     print "Particles > 1.0um / 0.1L air: " STR$(particles_10um2)
     print "Particles > 2.5um / 0.1L air: " STR$(particles_25um2)
     print "Particles > 5.0um / 0.1L air: " STR$(particles_50um2)
     print "Particles > 10.0 um / 0.1L air: " STR$(particles_100um2)
   END IF
 END IF
END SUB
 
 
 data 66,77, 0,28,0,2,0,4,0,4,0,2,0,4,0,4
 data 2,97 ,0,24,0,28,0,2,0,0,0,0,23,0,2,111


Jim
VK7JH
MMedit   MMBasic Help
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 04:20am 27 Jan 2021
Copy link to clipboard 
Print this post

@ Jim, Could there be a problem in reconstructing the string?

@ Lew, Maybe you could add something like the code in red below to Jim's code (or your own) so you could supply some usable data? You should be able to paste that into the forum.

for n = 1 to 32
  read p
  b$ = b$+chr$(p)
next n

for n = 1 to 32
   print asc(mid$(b$,n,1)); : print ",";
next n
print


decode


Bill
Keep safe. Live long and prosper.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5903
Posted: 04:39am 27 Jan 2021
Copy link to clipboard 
Print this post

  Turbo46 said  @ Jim, Could there be a problem in reconstructing the string?

Bill

Yes, I had to guess a few bytes but apart from the one high-byte difference, the rest makes sense.
That's why I would have liked more data to play with.

Jim
VK7JH
MMedit   MMBasic Help
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1676
Posted: 09:04am 27 Jan 2021
Copy link to clipboard 
Print this post

  TassyJim said  You have to compare your calculated checksum with the devices checksum
to get your values, you multiply the high byte by 256 and add the low byte.

Sorry about the time difference and delays.

Where did you get the *256?
In the datasheet it says
Check code=Start character1+Start character2+........+data13Low 8 bits

Could that mean add characters 1 - 12 + data 13 low bit?
then if it's the same as characters 31 and 32 it's valid?
OR does it mean add characters 1 + 2 + data 12 low 8 bits?





As the first 4 bytes are always 66,77,0,28 in valid data and I guess I could use that instead of the acual checksum sent to ensure valid data?
it's just the fact I can't figure out how the checksum is calculated that's bugging me.

I don't "need" all the returned values, it's only to show the air quality in the room here with me so  PM2.5 and PM10 are fine

I plan on using colours with the numbers to see if I need to turn the air filter on or not, I have asthma and dust particles doesn't help at all.

What I would like to do but not sure how is to compare the checksum with the previous checksum and if it's identical then ignore the data and wait for the next read
I only want it to update when the data changes.

Data as requested below the code
This code works but it's for the arduino
boolean readPMSdata(Stream *s) {
 if (! s->available()) {
   return false;
 }
 
 // Read a byte at a time until we get to the special '0x42' start-byte
 if (s->peek() != 0x42) {
   s->read();
   return false;
 }

 // Now read all 32 bytes
 if (s->available() < 32) {
   return false;
 }
   
 uint8_t buffer[32];    
 uint16_t sum = 0;
 s->readBytes(buffer, 32);

 // get checksum ready
 for (uint8_t i=0; i<30; i++) {
   sum += buffer[i];
 }

 /* debugging
 for (uint8_t i=2; i<32; i++) {
   Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
 }
 Serial.println();
 */
 
 // The data comes in endian'd, this solves it so it works on all platforms
 uint16_t buffer_u16[15];
 for (uint8_t i=0; i<15; i++) {
   buffer_u16[i] = buffer[2 + i*2 + 1];
   buffer_u16[i] += (buffer[2 + i*2] << 8);
 }

 // put it into a nice struct :)
 memcpy((void *)&data, (void *)buffer_u16, 30);

 if (sum != data.checksum) {
   Serial.println("Checksum failure");
   return false;
 }
 // success!
 return true;
}
copied from https://how2electronics.com/interfacing-pms5003-air-quality-sensor-arduino/

data as requested, hopefully it's enough

  Quote   66 77 0 28 0 2 0 2 0 2 0 2 0 2 0 2 2 13 0 165 0 16 0 1 0 0 0 0 151 0 2 19
66 77 0 28 0 2 0 2 0 2 0 2 0 2 0 2 2 13 0 165 0 16 0 1 0 0 0 0 151 0 2 19
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 64 0 176 0 16 0 1 0 0 0 0 151 0 2 85
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 64 0 176 0 16 0 1 0 0 0 0 151 0 2 85
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 64 0 176 0 16 0 1 0 0 0 0 151 0 2 85
66 77 0 28 0 2 0 2 0 2 0 2 0 2 0 2 2 58 0 176 0 16 0 1 0 0 0 0 151 0 2 75
66 77 0 28 0 2 0 2 0 2 0 2 0 2 0 2 2 58 0 176 0 16 0 1 0 0 0 0 151 0 2 75
66 77 0 28 0 3 0 3 0 3 0 3 0 3 0 3 2 58 0 176 0 16 0 1 0 0 0 0 151 0 2 81
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 22 0 164 0 13 0 1 0 0 0 0 151 0 2 28
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 22 0 164 0 13 0 1 0 0 0 0 151 0 2 28
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 22 0 164 0 13 0 1 0 0 0 0 151 0 2 28
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 2 22 0 164 0 13 0 2 0 1 0 1 151 0 2 33
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 2 22 0 164 0 13 0 2 0 1 0 1 151 0 2 33
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 2 22 0 164 0 13 0 2 0 1 0 1 151 0 2 33
66 77 0 28 0 1 0 2 0 3 0 1 0 2 0 3 2 16 0 162 0 16 0 2 0 1 0 1 151 0 2 22
66 77 0 28 0 1 0 2 0 3 0 1 0 2 0 3 2 16 0 162 0 16 0 2 0 1 0 1 151 0 2 22
66 77 0 28 0 1 0 2 0 3 0 1 0 2 0 3 2 16 0 162 0 16 0 2 0 1 0 1 151 0 2 22
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 242 0 150 0 15 0 2 0 1 0 1 151 0 2 238
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 242 0 150 0 15 0 2 0 1 0 1 151 0 2 238
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 242 0 150 0 15 0 2 0 1 0 1 151 0 2 238
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 254 0 154 0 15 0 2 0 1 0 1 151 0 2 254
66 77 0 28 0 1 0 2 0 2 0 1 0 2 0 2 1 254 0 154 0 15 0 2 0 1 0 1 151 0 2 248
66 77 0 28 0 1 0 2 0 2 0 1 0 2 0 2 1 254 0 154 0 15 0 2 0 1 0 1 151 0 2 248
66 77 0 28 0 1 0 2 0 3 0 1 0 2 0 3 1 242 0 150 0 22 0 2 0 1 0 1 151 0 2 241
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 242 0 150 0 22 0 2 0 1 0 1 151 0 2 247
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 242 0 150 0 22 0 2 0 1 0 1 151 0 2 247
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 230 0 145 0 26 0 1 0 1 0 1 151 0 2 233
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 230 0 145 0 26 0 1 0 1 0 1 151 0 2 233
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 230 0 145 0 26 0 1 0 1 0 1 151 0 2 233
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 224 0 143 0 26 0 1 0 1 0 1 151 0 2 225
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 224 0 143 0 26 0 1 0 1 0 1 151 0 2 225
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 224 0 143 0 26 0 1 0 1 0 1 151 0 2 225
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 224 0 147 0 30 0 1 0 1 0 1 151 0 2 233
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 224 0 147 0 30 0 1 0 1 0 1 151 0 2 233
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 224 0 147 0 30 0 1 0 1 0 1 151 0 2 233
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 212 0 139 0 29 0 1 0 1 0 1 151 0 2 212
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 212 0 139 0 29 0 1 0 1 0 1 151 0 2 212
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 212 0 139 0 29 0 1 0 1 0 1 151 0 2 212
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 2 43 0 153 0 18 0 1 0 1 0 1 151 0 2 47
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 2 43 0 153 0 18 0 1 0 1 0 1 151 0 2 47
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 2 43 0 153 0 18 0 1 0 1 0 1 151 0 2 47
66 77 0 28 0 2 0 3 0 5 0 2 0 3 0 5 2 64 0 160 0 18 0 2 0 2 0 2 151 0 2 80
66 77 0 28 0 2 0 3 0 5 0 2 0 3 0 5 2 64 0 160 0 18 0 2 0 2 0 2 151 0 2 80
66 77 0 28 0 2 0 3 0 5 0 2 0 3 0 5 2 64 0 160 0 18 0 2 0 2 0 2 151 0 2 80
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 19 0 145 0 13 0 1 0 1 0 1 151 0 2 8
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 19 0 145 0 13 0 1 0 1 0 1 151 0 2 8
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 19 0 145 0 13 0 1 0 1 0 1 151 0 2 8
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 1 0 141 0 14 0 1 0 1 0 1 151 0 1 243
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 1 0 141 0 14 0 1 0 1 0 1 151 0 1 243
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 1 0 141 0 14 0 1 0 1 0 1 151 0 1 243
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 194 0 129 0 16 0 1 0 1 0 1 151 0 2 167
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 194 0 129 0 16 0 1 0 1 0 1 151 0 2 167
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 194 0 129 0 16 0 1 0 1 0 1 151 0 2 167
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 200 0 129 0 15 0 1 0 1 0 1 151 0 2 172
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 200 0 129 0 15 0 1 0 1 0 1 151 0 2 172
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 200 0 129 0 15 0 1 0 1 0 1 151 0 2 172
66 77 0 28 0 1 0 2 0 3 0 1 0 2 0 3 1 200 0 129 0 17 0 1 0 1 0 1 151 0 2 172
66 77 0 28 0 1 0 2 0 3 0 1 0 2 0 3 1 200 0 129 0 17 0 1 0 1 0 1 151 0 2 172
66 77 0 28 0 1 0 2 0 3 0 1 0 2 0 3 1 200 0 129 0 17 0 1 0 1 0 1 151 0 2 172
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 185 0 127 0 17 0 2 0 1 0 1 151 0 2 158
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 185 0 127 0 17 0 2 0 1 0 1 151 0 2 158
66 77 0 28 0 2 0 2 0 3 0 2 0 2 0 3 1 185 0 127 0 17 0 2 0 1 0 1 151 0 2 158
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 224 0 140 0 16 0 2 0 1 0 1 151 0 2 211
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 224 0 140 0 16 0 2 0 1 0 1 151 0 2 211
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 224 0 140 0 16 0 2 0 1 0 1 151 0 2 211
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 206 0 138 0 19 0 2 0 1 0 1 151 0 2 194
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 206 0 138 0 19 0 2 0 1 0 1 151 0 2 194
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 1 206 0 138 0 19 0 2 0 1 0 1 151 0 2 194
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 251 0 149 0 21 0 2 0 1 0 1 151 0 2 254
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 251 0 149 0 21 0 2 0 1 0 1 151 0 2 254
66 77 0 28 0 2 0 3 0 4 0 2 0 3 0 4 1 251 0 149 0 21 0 2 0 1 0 1 151 0 2 254
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 13 0 153 0 21 0 1 0 0 0 0 151 0 2 16
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 13 0 153 0 21 0 1 0 0 0 0 151 0 2 16
66 77 0 28 0 2 0 3 0 3 0 2 0 3 0 3 2 13 0 153 0 21 0 1 0 0 0 0 151 0 2 16
66 77 0 28 0 1 0 3 0 3 0 1 0 3 0 3 2 58 0 165 0 26 0 2 0 0 0 0 151 0 2 77
66 77 0 28 0 1 0 3 0 3 0 1 0 3 0 3 2 58 0 165 0 26 0 2 0 0 0 0 151 0 2 77
66 77 0 28 0 1 0 3 0 3 0 1 0 3 0 3 2 58 0 165 0 26 0 2 0 0 0 0 151 0 2 77

last question
do I add the bytes together to get the values?
in the last data line that would be
1,3,3,1,3,3,60.165,26,2,0 and 79 is the checksum?
Edited 2021-01-27 19:12 by lew247
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 10:41am 27 Jan 2021
Copy link to clipboard 
Print this post

  Quote  Where did you get the *256?

The data consists of 16 bits. The low byte contains the value 0-255. The high byte holds the values of 256 and up. To get the 16 bit value you must multiply the high byte by 256 and add it to the low byte to get the full 16 bit value.

  Quote  Check code=Start character1+Start character2+........+data13Low 8 bits

That is a bit confusing but I think it does mean to add all of the bytes from Start character1 to the data byte13low to get the checksum which is a 16 bit number. As Jim has done.

  Quote  do I add the bytes together to get the values?
in the last data line that would be
1,3,3,1,3,3,60.165,26,2,0 and 79 is the checksum?

No. As above you must multiply the high byte by 256 and add it to the low byte to get the 16 bit value. So the checksum is:
(2 * 256) + 77 = 589 decimal.

Check out Jim's code and try to understand it.

I haven't put your data into Jim's program yet.

Bill
Keep safe. Live long and prosper.
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 10:48am 27 Jan 2021
Copy link to clipboard 
Print this post

Addendum, I plugged the last line of your data into Jim's program and it gave the correct result - well the checksum was correct.

Bill
Keep safe. Live long and prosper.
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1676
Posted: 12:20pm 27 Jan 2021
Copy link to clipboard 
Print this post

I get what you're saying, that the checksum works BUT
it's not the same as comparing it to the checksum sent by the device?

The checksum send by the device is asc(mid$(b$,31,1))+asc(mid$(b$,32,1))
Surely the checksum generated should match the checksum sent?

in Jim's code
if c*256 + d = 28 then ' data length is correct we probably have valid data
but C ALWAYS = 0 and ALWAYS = 28 with valid data so doing c*256 will always give the same result

In the arduino code there is no multiplying *256


IF I understand this correctly
// Now read all 32 bytes
if (s->available() < 32) {
  return false;
}        
Get data fromINPUT$(1,#1)

uint8_t buffer[32];    
uint16_t sum = 0;
s->readBytes(buffer, 32);
Read 32 bytes into the buffer

// get checksum ready
for (uint8_t i=0; i<30; i++) {
  sum += buffer[i];
}
If buffer is less than 30 then loop

/* debugging
for (uint8_t i=2; i<32; i++) {
  Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
*/
Print the values (hex??) of the buffer?


THIS IS THE BIT I DO NOT UNDERSTAND
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i=0; i<15; i++) {
  buffer_u16[i] = buffer[2 + i*2 + 1];
  buffer_u16[i] += (buffer[2 + i*2] << 8);
}
No idea what's going on above - aparently << means shift left by 8 bits but that means nothing to me

Edited 2021-01-27 22:25 by lew247
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 12:50pm 27 Jan 2021
Copy link to clipboard 
Print this post

  Quote  I get what you're saying, that the checksum works BUT
it's not the same as comparing it to the checksum sent by the device?

The checksum sent by the device is high byte 2, low byte 77.
(2 * 256) + 77 = 589 decimal.
It does agree with the calculated checksum.

Take a 16 bit binary word x = 0000000000000001 and shift it left 8 times and you get 000000010000000. That equals 256. instead of using (x * 256) you could just as easily use (x<<8) which would give the same result.


Bill
Keep safe. Live long and prosper.
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1676
Posted: 12:54pm 27 Jan 2021
Copy link to clipboard 
Print this post

  Turbo46 said  
The data consists of 16 bits. The low byte contains the value 0-255. The high byte holds the values of 256 and up. To get the 16 bit value you must multiply the high byte by 256 and add it to the low byte to get the full 16 bit value.
Bill


Surely this can't be right?
If that is the case then with this data
66 77 0 28 0 31 0 43 0 48 0 26 0 38 0 47 22 77 6 77 0 230 0 17 0 6 0 2 151 2 3 226
then the
PM10 particle count is data 10* 256 + data 9  which is 48*256+0 = 12288
PM2.5 particle count is data 8* 256 + data 7  which is 43*256+1 = 11088
PM1.0 particle count is data 6* 256 + data 5  which is 31*256+0 = 7936

Those values seem really high?
Especially for indoors
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1593
Posted: 01:14pm 27 Jan 2021
Copy link to clipboard 
Print this post

Sorry but I see the data for PM10 as 0, 48.
  Quote  66 77 0 28 0 31 0 43 0 48 0 26 0 38 0 47 22 77 6 77 0 230 0 17 0 6 0 2 151 2 3 226

PM 2.5 = 0, 43
PM 1.0 = 0, 31

I don't see where you get your values from.

Bill
Keep safe. Live long and prosper.
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1676
Posted: 01:24pm 27 Jan 2021
Copy link to clipboard 
Print this post

  Turbo46 said  Sorry but I see the data for PM10 as 0, 48.
  Quote  66 77 0 28 0 31 0 43 0 48 0 26 0 38 0 47 22 77 6 77 0 230 0 17 0 6 0 2 151 2 3 226

PM 2.5 = 0, 43
PM 1.0 = 0, 31

I don't see where you get your values from.

Bill
  Turbo46 said  
The data consists of 16 bits. The low byte contains the value 0-255. The high byte holds the values of 256 and up. To get the 16 bit value you must multiply the high byte by 256 and add it to the low byte to get the full 16 bit value.
Bill
 
     Page 1 of 2    
Print this page
© JAQ Software 2024