Coming Soon: Teensy-LC (low cost Teensy)

Status
Not open for further replies.
Yup, the ordinary Wire library works on Teensy-LC, but it doesn't support the 2nd port and it has far fewer features than i2c_t3. It only provides the basic level of Arduino functionality.

Later this coming week, I'm planning to really look into the Wire library, using that troublesome Lidar module. It's been sitting here collecting dust for a couple weeks while I've been scrambling to keep up with the rapid Arduino releases. I have no intention to turn Wire into the larger feature set of i2c_t3, but at the very least I do intend to support Wire1 and implement setClock, setSDA and setCLK, and do some sort of timeout or other way to recover from misbehaving I2C devices.
 
Good to hear that guys. At this point indeed the second bus is most important for me indeed. I have hooked a analog port multiplexer to the second i2c (all SMD so not easy to connect it to the primary port).
 
In the code of the Wire library you are using, there is a comment that external pull ups must be used. Will the newer or updated library resolve that? I have a Teensy 2.0 and it works fine with the internal pull ups. I realize these are different processors. Also, there is a version of the Wire library out there that includes a twi library that has additional code to prevent I2C lockups, it is called WSWire. Do we need to do that with the TeensyLC? Maybe the new processor also does not have this lock-up problem?

Matt


Yup, the ordinary Wire library works on Teensy-LC, but it doesn't support the 2nd port and it has far fewer features than i2c_t3. It only provides the basic level of Arduino functionality.

Later this coming week, I'm planning to really look into the Wire library, using that troublesome Lidar module. It's been sitting here collecting dust for a couple weeks while I've been scrambling to keep up with the rapid Arduino releases. I have no intention to turn Wire into the larger feature set of i2c_t3, but at the very least I do intend to support Wire1 and implement setClock, setSDA and setCLK, and do some sort of timeout or other way to recover from misbehaving I2C devices.
 
In the code of the Wire library you are using, there is a comment that external pull ups must be used. Will the newer or updated library resolve that?
I believe the answer regarding pullups is it is not something the library can work around. The ARM processors used in the Teensy 3.0/3.1/LC just do not have the right hardware that the library can enable internal pull-ups and have them work correctly for i2c.
 
Yes, that seems reasonable. My application uses very few pins. Do you think it could be possible to connect two unused pins to each of the I2C connections needing pull up and set the pull ups on those unused pins to true? I am really trying to limit the number of components used and even getting rid of 2 resistors is a help.

I believe the answer regarding pullups is it is not something the library can work around. The ARM processors used in the Teensy 3.0/3.1/LC just do not have the right hardware that the library can enable internal pull-ups and have them work correctly for i2c.
 
I have a Teensy 2.0 and it works fine with the internal pull ups

Even on the AVR, while it may "work" with the internal pullups for certain device configurations, it is out of spec and doesn't always work.
The internal pullups are simply too weak.
Consider yourself lucky if it works for your situation without the external pullups.

--- bill
 
Thanks, that is good information. I bet it works because I am doing I2C from one Atmel chip to another. I guess I will be prepared to wire up a couple of pull-ups since I will be going from an Atmel to the ARM Cortex-M0+.

Matt
 
Yes, that seems reasonable. My application uses very few pins. Do you think it could be possible to connect two unused pins to each of the I2C connections needing pull up and set the pull ups on those unused pins to true? I am really trying to limit the number of components used and even getting rid of 2 resistors is a help.

This is an interesting solution, especially if you have a lot of unused pins. The internal pullups are weak for I2C, but they might work for a 100k rate. However if you parallel a few pins together (with others configured as INPUT_PULLUP) you might get something approaching a reasonable pullup value. It's worth a try if you can do it.
 
lower resistance pullup improves noise immunity. Like 4.7K, depending on wire length. Pay attention to a good common ground wire too.
 
The weak internal pull-ups in MCUs, say, 40K, don't bring much benefit to improving the rise time as you see on that dsscircuits.com web page. Unless the device is battery powered and there's a lot usage of the I2C, then I'd go with 1.5K or so.
The length of and capacitance of the wiring you use has a big affect.
 
The device I am constructing will receive data in slave mode over I2C then send the data using serial out a bluetooth serial module continuously. It will be battery powered but only needs to be able to run for an hour or so per charge of a moderately large LiPo battery. It should be plenty of power so the 1.5K should work well. I am going to hook my O'Scope up and check the rise times just to make sure all is OK.

The weak internal pull-ups in MCUs, say, 40K, don't bring much benefit to improving the rise time as you see on that dsscircuits.com web page. Unless the device is battery powered and there's a lot usage of the I2C, then I'd go with 1.5K or so.
The length of and capacitance of the wiring you use has a big affect.
 
OK Guys, Last night I went ahead and hooked up my O-Scope to the I2C lines, and I found that the internal pull ups were really rounding off those wave forms. So I grabbed a couple of 1.5K resistors, turned off the internal pull ups and wired them in, and like magic, the wave forms squared off nicely. So, thanks bperrybap, it was as you explained, "working" but certainly not very clean.

This may also fix my problem where the i2C gets into a locked up state, the poor performance on the bus may be causing it, so I will test that as well going forward.

Thanks to you all!

Matt
 
on the 'scope, pay attention to how close to 0 volts the signals go. There's less margin for error in a logic 0 than a logic 1, in terms of voltage.
 
Hi All

Just an idea to make a "really cheap" version in case this would be of interest in the future.

The Teensy LC uses the KL26Z64 which costs $1.50 in quantity but needs the Mini54tan for loading code and a crystal for the USB to be reliable.

The KL27Z64 costs $1.52 in the same quantity but has two additional features that save overall component costs:
1 - it doesn't need a crystal since it has an internal 48MHz clock which supports synchronisation to a USB host and so allows crystal-less USB device operation
2 - It has an internal loader that allows programming it via USB, UART, I2C or SPI and so doesn't require a Mini54tan

I have seen this board using it http://www.coffeebrain.org/blog/distribucion-de-pines-capuccino-kl27/

Of course the USB protocol (HID based) for loading is not the same but it could certainly be supported with a modification in the Teensy Loader application.
There may be other (slight) differences to consider but may be worth checking out.

Regards

Mark
 
OK Guys, Last night I went ahead and hooked up my O-Scope to the I2C lines, and I found that the internal pull ups were really rounding off those wave forms. So I grabbed a couple of 1.5K resistors, turned off the internal pull ups and wired them in, and like magic, the wave forms squared off nicely. So, thanks bperrybap, it was as you explained, "working" but certainly not very clean.

This may also fix my problem where the i2C gets into a locked up state, the poor performance on the bus may be causing it, so I will test that as well going forward.

Thanks to you all!

Matt

So, I wired up my TeensyLC to be a slave, and I can not get it to receive any data. I have external pull ups and am using pins 18 & 19 for the I2C. Am I missing something? I have gotten this setup to work with the Teensy2.0 and the Trinket from Adafruit.

I can see on my scope that the master is sending out the data, the TeensyLC just does not seem to be receiving it.

Matt
 
Last edited:
I can see on my scope that the master is sending out the data, the TeensyLC just does not seem to be receiving it.

I tested this with both pairs of master/slave examples in the Wire library. Both worked great.

Are you using different code? I could investigate if you post (hopefully small, but complete) code for both sides and a photo of how you've actually wired them up. If you post something for me to test, please use two Teensy boards. I don't have any Adafruit Trinkets.
 
I tested this with both pairs of master/slave examples in the Wire library. Both worked great.

Are you using different code? I could investigate if you post (hopefully small, but complete) code for both sides and a photo of how you've actually wired them up. If you post something for me to test, please use two Teensy boards. I don't have any Adafruit Trinkets.

Paul,

I am using Pins 18 and 19 with external pull up resistors of 1.5k for the I2C in the same configuration I used to receive the data using the Teensy2.0 (running at 3V3). I will take a picture tonight to show. Unfortunately, I am trying to interface to a purchased device so I do not have control over that device. Through research I know that the device I am connecting to is AVR based and is acting as a Master on the I2C and transmitting data to all slaves on the bus. The program below is almost exactly what I have for the Teensy2.0, but for the 2.0 I am using the WSWire library, because it includes code to prevent the I2C lockup that can sometimes happen. Even without the lockup code, I would expect to get some of the data before the bus locks up, but I get zero calls to the receiveEvent routine.

Here is the program I am using:

Code:
#include <Wire.h>

int ledPin = 13;//on TeensyLC
int mindex = 0;
int packetsRxed = 0;
unsigned long lastPacketRxedTime = 0L;
unsigned long now = 0L;
int buffer[32];
boolean dataAvailable = false;

//Define hardware serial port #1 on the TeensyLC as btModule
#define btModule Serial1 


//////////////UTILITY/////////////////////////

boolean ledOn(){
  return digitalRead(ledPin);
}

void toggleLED(){
  digitalWrite(ledPin,!ledOn());
}


//////////////SETUP/////////////////////////

void setup()
{
  //Serial.begin(19200);           // start serial for output
  btModule.begin(19200);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin,HIGH); //start LED as ON.

  //Blink the LED 2 times and leave on... 
  //The LED starts as ON, so you get ON, OFF, ON, OFF, steady ON
  for (int i=0; i <2 ; i++){
    delay(250); 
    toggleLED(); //off
    delay(250);
    toggleLED(); //on
  }

  //Serial.println("Starting");
  
  Wire.begin(0x00);                // get general call
  Wire.onReceive(receiveEvent); // register event
  lastPacketRxedTime = millis();//initialize the led toggle timer
}


//////////////LOOP/////////////////////////
void loop()
{  
  delay(5);
  now = millis();
  
  //Blinking LED means data is being received, steady ON means no data
  //has been received for awhile.
  //
  //Toggle the LED after 10 packets have been received OR  
  //more than 1 second has gone by and there is a new packet received. This keeps
  //the LED blinking even if the data is coming in slowly...
  if ((packetsRxed > 10) || (dataAvailable & ((now - lastPacketRxedTime) > 1000L))){
    toggleLED();
    packetsRxed = 0;
  }

  //if it has been 3 seconds since the last packet was received and there is
  //not new data coming in and the LED is off,
  //turn the led back on to show we are still alive
  if (((now - lastPacketRxedTime) > 3000L) && !ledOn() && !dataAvailable){
    toggleLED();
  }
  
  if (dataAvailable) {
    dataAvailable = false;

    //Serial.print(mindex);
    //Serial.print(":");

    //write it to the Bluetooth SPP (and Serial port for debugging)...
    for (int i=0; i<mindex; i++){
      btModule.write(buffer[i]);

      //Serial.print(buffer[i],HEX);
      //Serial.print(':');
    }
    //Serial.println("[EOM]");
  }
}

//////////////EVENT/////////////////////////

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
// Get the data and get out of this routine. Set a flag to 
// transmit the data on the main loop.
//
void receiveEvent(int howMany){
  if (howMany < 1) // Sanity-check
        return;
  if (howMany > 32) // Also insane number
        return;
    
    packetsRxed++;
    int i = 0;
    while(Wire.available())
      buffer[i++] = Wire.read(); // receive bytes
    
    //leave mindex alone for as long as possible...
    mindex = i;
    dataAvailable = true;
}
 
Is there any code available I could run on a Teensy 2.0, so when I connect it to a Teensy-LC running this code, I can reproduce the lockup?

Actually, before that... have you tried 1.23-beta1 yet?

https://forum.pjrc.com/threads/28499-Teensyduino-1-23-Beta-1-Available

Quite a bit of work was done to the Wire library to prevent lockups with using the Lidar Lite, which does all sorts of wrong I2C stuff. Maybe 1.23-beta1 will solve the problems you're seeing? It's easy to try.
 
Status
Not open for further replies.
Back
Top