Test firmware for the Supermote hardware.

Dependencies:   K30_I2C libxDot-mbed5

Fork of K30_I2C_Program by Hux Connect

HPM/hpm.cpp

Committer:
bjenkins
Date:
2018-09-14
Revision:
3:2ab969b31f6b
Parent:
2:680fc2690d10

File content as of revision 3:2ab969b31f6b:

#include "mbed.h"
#include "hpm.h"


HPM::HPM(Serial* device, Serial* debug): _device(device), _debug(debug)
{

}

bool HPM::init(void)
{
    _debug->printf("Initialising the PM sensor\r\n");
    wait(1.0);

    _debug->printf("PM baud rate set to 9600\r\n");
    _device->baud(9600);
    wait(0.1);
   
    // Stop autosend
    if (!this->stop_autosend())
    {
        _debug->printf("Stop autosend failed\r\n");
        return 0;
    }
    _debug->printf("Stop autosend success\r\n");
    
    // Start fan
    if (!this->start_measurement())
    {
        _debug->printf("Start measurement failed\r\n");
        return 0;
    }
    _debug->printf("Start measurement success\r\n");
    
    return 1;
}
    
bool HPM::start_measurement(void)
{
    clear_rx_buffer();

    // First, we send the command
    unsigned char start_measurement[] = {0x68, 0x01, 0x01, 0x96 };
    for (int i=0; i<sizeof(start_measurement); i++)
    {
        while (!_device->writeable());       // wait until we can write to the port
        _device->putc(start_measurement[i]);  
    }
  
    //Then we wait for the response
    while (!_device->readable()) {} // wait until chars arrive
    char read1 = _device->getc();
    while (!_device->readable()) {} // wait until chars arrive
    char read2 = _device->getc();
    
    // Test the response
    if ((read1 == 0xA5) && (read2 == 0xA5)){
        return 1;   // ACK
    }
    else if ((read1 == 0x96) && (read2 == 0x96))
    {
        _debug->printf ("NACK\r\n");
        return 0;   // NACK
    }
    else return 0;
}

bool HPM::stop_measurement(void)
{
    clear_rx_buffer();

    // First, we send the command
    unsigned char stop_measurement[] = {0x68, 0x01, 0x01, 0x95 };
    for (int i=0; i<sizeof(stop_measurement); i++)
    {
        while (!_device->writeable());       // wait until we can write to the port
        _device->putc(stop_measurement[i]); 
    }
  
  
    //Then we wait for the response
    while (!_device->readable()) {} // wait until chars arrive
    char read1 = _device->getc();
    while(!_device->readable());
    char read2 = _device->getc();
    
    // Test the response
    if ((read1 == 0xA5) && (read2 == 0xA5)){
        return 1;   // ACK
    }
    else if ((read1 == 0x96) && (read2 == 0x96))
    {
        _debug->printf ("NACK\r\n");
        return 0;   // NACK
    }
    else return 0;
}

bool HPM::read_measurement (long int &PM25, long int &PM10)
{
    clear_rx_buffer();        
    
    // Send the command 0x68 0x01 0x04 0x93
    unsigned char read_particle[] = {0x68, 0x01, 0x04, 0x93 };
    for (int i=0; i<sizeof(read_particle); i++)
    {
        while (!_device->writeable());       // wait until we can write to the port
        _device->putc(read_particle[i]);   
    }
  
    // A measurement can return 0X9696 for NACK
    // Or can return eight bytes if successful
    // We wait for the first two bytes
    while(!_device->readable());
    unsigned char HEAD = _device->getc();
    
    while(!_device->readable());
    unsigned char LEN = _device->getc();
  
    // Test the response
    if ((HEAD == 0x96) && (LEN == 0x96))
    {
        _debug->printf("NACK");
        return 0;
    }
    else if ((HEAD == 0x40) && (LEN == 0x05))
    {
        // The measuremet is valid, read the rest of the data 
        // wait for the next byte
        while(!_device->readable());
        unsigned char COMD = _device->getc();
        
        while(!_device->readable());
        unsigned char DF1 = _device->getc();
        
        while(!_device->readable());
        unsigned char DF2 = _device->getc();
             
        while(!_device->readable());
        unsigned char DF3 = _device->getc();
           
        while(!_device->readable());
        unsigned char DF4 = _device->getc();
         
        while(!_device->readable());
        unsigned char CS = _device->getc();
          
        // Now we shall verify the checksum
        unsigned int cs_calc = 65536;
        cs_calc -= HEAD - LEN - COMD - DF1 - DF2 - DF3 - DF4;
        cs_calc %= 256;
        
        if (((0x10000 - HEAD - LEN - COMD - DF1 - DF2 - DF3 - DF4) % 0XFF) != CS)
        {
            _debug->printf("Checksum fail\r\n");
            _debug->printf ("HEAD=%02x LEN=%02x COMD=%02x DF1=%02x DF2=%02x DF3=%02x DF4=%02x CS=%02x, cs_calc=%02x\r\n", HEAD, LEN, COMD, DF1, DF2, DF3, DF4, CS, cs_calc);
            return 0;
        }
        else
        {
            // Checksum OK, we compute PM2.5 and PM10 values
            PM25 = DF1 * 256 + DF2;
            PM10 = DF3 * 256 + DF4;
            return 1;
        }
    }
    
    _debug->printf ("HEAD=%X, LEN=%X\r\n", HEAD, LEN);
    return 0;
}

bool HPM::stop_autosend(void)
{
    clear_rx_buffer();

    // Stop auto send
    unsigned char stop_autosend[] = {0x68, 0x01, 0x20, 0x77 };
    for (int i=0; i<sizeof(stop_autosend); i++)
    {
        while (!_device->writeable());       // wait until we can write to the port
        _device->putc(stop_autosend[i]); 
    }
    
    //Then we wait for the response
    while(!_device->readable());
    char read1 = _device->getc();
    while(!_device->readable());
    char read2 = _device->getc();
    
    // Test the response
    if ((read1 == 0xA5) && (read2 == 0xA5)){
        // ACK
        return 1;
    }
    else if ((read1 == 0x96) && (read2 == 0x96))
    {
        // NACK
        _debug->printf ("NACK\r\n");
        return 0;
    }
    else 
    {
        _debug->printf ("stop_autosend() output is %X%X\r\n", read1, read2);
        return 0;
    }
}

bool HPM::start_autosend(void)
{
    clear_rx_buffer();

    // Start auto send
    unsigned char start_autosend[] = {0x68, 0x01, 0x40, 0x57 };
    for (int i=0; i<sizeof(start_autosend); i++)
    {
        while (!_device->writeable());       // wait until we can write to the port
        _device->putc(start_autosend[i]); 
    }  

    //Then we wait for the response
    while(!_device->readable());
    char read1 = _device->getc();
    while(!_device->readable());
    char read2 = _device->getc();
    // Test the response
    if ((read1 == 0xA5) && (read2 == 0xA5)){
        // ACK
        return 1;
    }
    else if ((read1 == 0x96) && (read2 == 0x96))
    {
        // NACK
        _debug->printf ("NACK\r\n");
        return 0;
    }
    else
    {
        _debug->printf ("start_autosend() output is %X%X\r\n", read1, read2);
        return 0;
    }
}

void HPM::clear_rx_buffer(void)
{
    // ensure the Rx buffer is empty. clear out the crap
    while (_device->readable())
    {
        unsigned char dummy = _device->getc();
    }
}