Teensy 3.0 and co2 sensor with UART

Status
Not open for further replies.

Enje

Member
Hi,
I've been trying to get a project involving co2-measurements going, but I seem to be stuck at what odd to be the most basic stuff.

I had no problems going through all the tutorials, and the fastspi_led2 library(will be part of the project eventually),
but this serial stuff just gets me stuck.

--------------
What I have is a Teensy 3.0 and a SenseAir K-30 module.

G0 (k30) goes to the common ground (GND) of the Teensy, and G+ (k30) gets power from Vin (Teensy).
Rxd (k30) goes to 9 (Teensy) and Txd (k30) goes to 10 (Teensy).
[I am using the UART Terminal on the k30.]

----------------------------
Now to the problem:
I get no response.

I tried using the Arduino example (see K30_basic example below), but 'while(!K_30_Serial.available())' got stuck in an infinite loop.
Then I went to try the kSeries.h from their example #2, but it does not support Teensy 3.0.

Now I figured that since that while-loop got stuck I should try work with a purely simplified code to try get contact with the module and went with something very simple (see Very_simple example below).
Nothing here either, the counter runs, but it can not seem to find the module.
Then I tried with a simple SoftwareSerial example (see simple_softwareSerial below).
Nothing here either.

Finally I changed pins and tried analogRead, and now the module at least said hello to me.
Not like that is going to help much though!

------------------------------------------
So the question is, what am I doing wrong:confused:

(I have thought of shifting the RxD and TxD signals from the k30 module down to 3.3V before they hit the Teensy,
but for the time beeing I am hoping for any usable output from the module before I expand stuff.

--------------------------------------------------------
Arduino example using SoftwareSerial.:
http://www.co2meters.com/Documentation/AppNotes/AN126-K3x-sensor-arduino-uart.pdf
K-30 datasheet.:
http://co2meters.com/Documentation/Datasheets/DS30-01%20-%20K30.pdf
Offical product sheet.:
http://www.senseair.se/wp-content/uploads/2012/02/PSP110_k30.pdf
kSeries.h from co2meter.:
http://www.co2meters.com/Documentation/AppNotes/AN126-K3x-sensor-arduino-uart.zip

K30_basic example:
Code:
/*
  Basic Arduino example for K-Series sensor
  Created by Jason Berger
  Co2meter.com  
*/


#include "SoftwareSerial.h"

SoftwareSerial K_30_Serial(9,10);  //Sets up a virtual serial port
                                    //Using pin 9 for Rx and pin 10 for Tx, because it is Serial2 on the Teensy


byte readCO2[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};  //Command packet to read Co2 (see app note)
byte response[] = {0,0,0,0,0,0,0};  //create an array to store the response

//multiplier for value. default is 1. set to 3 for K-30 3% and 10 for K-33 ICB
int valMultiplier = 1;

void setup() 
{
  // put your setup code here, to run once:
  Serial.begin(9600);         //Opens the main serial port to communicate with the computer
  K_30_Serial.begin(9600);    //Opens the virtual serial port with a baud of 9600
}

void loop() 
{
  sendRequest(readCO2);
  unsigned long valCO2 = getValue(response);
  Serial.print("Co2 ppm = ");
  Serial.println(valCO2);
  delay(2000);
  
}

void sendRequest(byte packet[])
{
  while(!K_30_Serial.available())  //keep sending request until we start to get a response
  {
    K_30_Serial.write(readCO2,7);
    delay(50);
  }
  
  int timeout=0;  //set a timeoute counter
  while(K_30_Serial.available() < 7 ) //Wait to get a 7 byte response
  {
    timeout++;  
    if(timeout > 10)    //if it takes to long there was probably an error
      {
        while(K_30_Serial.available())  //flush whatever we have
          K_30_Serial.read();
          
          break;                        //exit and try again
      }
      delay(50);
  }
  
  for (int i=0; i < 7; i++)
  {
    response[i] = K_30_Serial.read();
  }  
}

unsigned long getValue(byte packet[])
{
    int high = packet[3];                        //high byte for value is 4th byte in packet in the packet
    int low = packet[4];                         //low byte for value is 5th byte in the packet

  
    unsigned long val = high*256 + low;                //Combine high byte and low byte with this formula to get value
    return val* valMultiplier;
}

Very_simple example.:
Code:
int counter = 0;

void setup() {
	Serial.begin(38400);
        Serial2.begin(9600);
}
void loop() {
	Serial.println(counter); //only checking if the loop is running
        counter++;
        
	if (Serial2.available() > 0) {
		Serial.print("Found the device!");
	}
        delay(1000);
}

Simple_softwareSerial example.:
Code:
#include "SoftwareSerial.h"
SoftwareSerial k30(9,10);

int counter = 0;

void setup() {
	Serial.begin(38400);
        k30.begin(9600);
}
void loop() {
	Serial.println(counter); //only checking if the loop is running
        counter++;
        
	if (k30.available() > 0) {
		Serial.print("Found the device!");
	}
        delay(1000);
}

I am using Arduino IDE v1.0.5 with Teensy Loader v1.15 under WinXP.
 
Software-wise, this looks like it really should work.

(I have thought of shifting the RxD and TxD signals from the k30 module down to 3.3V before they hit the Teensy,
but for the time beeing I am hoping for any usable output from the module before I expand stuff.

What is the voltage on each of these (relative to ground), if you measure without the Teensy connected?
 
Same problem here.. Trying to switch over to from arduino to teensy using k30 co2 sensor.. no luck..
 
Same problem here.. Trying to switch over to from arduino to teensy using k30 co2 sensor.. no luck..
Nice to see that I am not alone in this boat.

Did you have any issues at all when using it with an Arduino?


Picture of my testing area:
BU9mD3J.jpg
 
@Enje - comparing your photo to the diagram on page 2 of this PDF, it looks like you've got RX and TX swapped.

The yellow wire is on the TX pin of the CO2 sensor. But it's going to pin 10 on Teensy3, which is TX2. That can't work, because they're both trying to transmit on the same wire!

You need to connect TX from the sensor to RX2 on Teensy3, and RX on the sensor to TX2 on Teensy3.

Earlier you said you had Teensyduino 1.15 installed. That ought to work. Please be aware there was a bug in 1.14 where an optimization added to Serial1 (which dramatically increases Serial1's efficiency at high baud rates) messed up some stuff on Serial2 and Serial3. That bug was fixed in 1.15, so Serial2 and Serial3 work great (as they did in 1.13). Just be aware that Serial2 had known bugs with version 1.14.
 
@Enje - comparing your photo to the diagram on page 2 of this PDF, it looks like you've got RX and TX swapped.
...
Ooohhh... man, now this is embarrassing.

A picture really can say more than a thousand words!

I changed it around a bit, now the yellow wire goes to 0 (rx1) and the pink goes to 1 (tx1).

I am using this code:
Code:
/*
  Basic Arduino example for K-Series sensor
  Created by Jason Berger
  Co2meter.com  
*/


#include "SoftwareSerial.h"

SoftwareSerial K_30_Serial(0,1);  //Sets up a virtual serial port


byte readCO2[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};  //Command packet to read Co2 (see app note)
byte response[] = {0,0,0,0,0,0,0};  //create an array to store the response

//multiplier for value. default is 1. set to 3 for K-30 3% and 10 for K-33 ICB
int valMultiplier = 1;

void setup() 
{
  // put your setup code here, to run once:
  Serial.begin(9600);         //Opens the main serial port to communicate with the computer
  K_30_Serial.begin(9600);    //Opens the virtual serial port with a baud of 9600
}

void loop() 
{
  sendRequest(readCO2);
  unsigned long valCO2 = getValue(response);
  Serial.print("Co2 ppm = ");
  Serial.println(valCO2);
  delay(2000);
  
}

void sendRequest(byte packet[])
{
  while(!K_30_Serial.available())  //keep sending request until we start to get a response
  {
    Serial.println("can not find it");
    K_30_Serial.write(readCO2,7);
    delay(50);
  }
  
  int timeout=0;  //set a timeoute counter
  while(K_30_Serial.available() < 7 ) //Wait to get a 7 byte response
  {
    timeout++;  
    Serial.println(timeout);
    if(timeout > 10)    //if it takes to long there was probably an error
      {
        while(K_30_Serial.available())  //flush whatever we have
          K_30_Serial.read();
          
          break;                        //exit and try again
      }
      delay(50);
  }
  
  for (int i=0; i < 7; i++)
  {
    response[i] = K_30_Serial.read();
  }  
}

unsigned long getValue(byte packet[])
{
    int high = packet[3];                        //high byte for value is 4th byte in packet in the packet
    int low = packet[4];                         //low byte for value is 5th byte in the packet

  
    unsigned long val = high*256 + low;                //Combine high byte and low byte with this formula to get value
    return val* valMultiplier;
}

And I get this output:
Code:
can not find it
Co2 ppm = 818
can not find it
Co2 ppm = 818
can not find it
can not find it
can not find it
can not find it
Co2 ppm = 818
can not find it
Co2 ppm = 818
can not find it
Co2 ppm = 818
can not find it
Co2 ppm = 818
can not find it
Co2 ppm = 817
can not find it
Co2 ppm = 816
can not find it
Co2 ppm = 815
can not find it
Co2 ppm = 816
can not find it
Co2 ppm = 816
can not find it
Co2 ppm = 815
can not find it
Co2 ppm = 814
can not find it
Co2 ppm = 814
can not find it
Co2 ppm = 814

It is strange how it at random times needs to try multiple writes to get a response (more than one 'can not find it'-line in a row).

Now it is just to try and get it working without the use of 'SoftwareSerial'. :D

I can not thank you enough Paul for pointing out that mix-up for me. :cool:


[I will try to update this post with progress, as it might be helpful to Tytek, and perhaps others as well.]
 
I'm glad you posted the photo so I could help. :)

Is this normal, for the sensor to not answer so many requests? If that doesn't happen on Arduino Uno, I'd really like to know so I can investigate.

You can probably eliminate SoftwareSerial by just replacing "K_30_Serial" with "Serial1". But it really doesn't matter. On Teensy3, when you use SoftwareSerial on a pair of pins that have serial capability, it just automatically translates your use of SoftwareSerial to the real hardware serial. That translation adds a tiny bit of software overhead, but compared to slow 9600 baud communication, it's extremely small.
 
I'm glad you posted the photo so I could help. :)

Is this normal, for the sensor to not answer so many requests? If that doesn't happen on Arduino Uno, I'd really like to know so I can investigate.

You can probably eliminate SoftwareSerial by just replacing "K_30_Serial" with "Serial1". But it really doesn't matter. On Teensy3, when you use SoftwareSerial on a pair of pins that have serial capability, it just automatically translates your use of SoftwareSerial to the real hardware serial. That translation adds a tiny bit of software overhead, but compared to slow 9600 baud communication, it's extremely small.
Tytek might be able to answer that, as I never really used the sensor with any Arduino device.

Those clusters of non-response is strange however. I even tried with a few other sensors, incase it was a defect, but it was the same behaviour there.
The module does not support higher than 9600 baud when using UART, so it is nothing I can do about that.

Earlier you said you had Teensyduino 1.15 installed. That ought to work. Please be aware there was a bug in 1.14 where an optimization added to Serial1 (which dramatically increases Serial1's efficiency at high baud rates) messed up some stuff on Serial2 and Serial3. That bug was fixed in 1.15, so Serial2 and Serial3 work great (as they did in 1.13). Just be aware that Serial2 had known bugs with version 1.14.
You are sadly not home free yet with this issue.

I did read about this issue before I even began doing anything with the sensor, and assumed that serial2 would work, I was wrong...

I have now re-tested the same code that I got to work with Serial1 on Serial2 and Serial3.
It does not want to work at all. It gets stuck in a loop of non-response (and this time the wiring was correct:rolleyes:).
 
I got mine working, just long enough to see some numbers scrolling on the serial.. My latest problem is trying to interface a ENC28J60 ethernet shield with Teensy 3.0 , all the libraries i've found are outdated and I wasted a whole day trying to get it to work... Do either of you have any experience with that ?
 
You can either spend $5-8 on eBay on cheap Ethernet shields that use the ENC2828J60 and spend hours upon hours just to figure out how to program the darned thing, or you can spend $21 and get a WIZ812mj and use the standard Ethernet library out of the box and then can go back to work on the essentials of the project.
If you're brave you can use a WIZ820io. There is a slightly modified Ethernet Library her on the forum to use with the WIZ820io.
 
I've not yet heard from anyone who ever got the ENC28J60 to work. Many have tried.

W5100 works great. Soon I'm going to tweak the Ethernet library for Teensy2 so both the W5100 and W5200 work easily.
 
Status
Not open for further replies.
Back
Top