Need help to using USB serial communication...

Status
Not open for further replies.

herald007

New member
Teensy 3.6 code
Code:
#include <SPI.h>
#include <i2c_t3.h>
#include <usb_serial.h>

//Pins
#define pin_mosi 11
#define pin_miso 12
#define pin_sck 13
#define pin_alt_sck 14
#define pin_lepton_cs 15
#define pin_sda 18
#define pin_scl 19

//FLIR Lepton sensor version
#define leptonVersion_2_0_shutter 0   //FLIR Lepton2 Shuttered
#define leptonVersion_3_0_shutter 1   //FLIR Lepton3 Shuttered
#define leptonVersion_2_0_noShutter 2 //FLIR Lepton2 Non-Shuttered
#define leptonVersion_2_5_shutter 3   //FLIR Lepton 2.5 Shuttered
#define leptonVersion_3_5_shutter 3   //FLIR Lepton 3.5 Shuttered

//Shutter mode
#define leptonShutter_manual 0
#define leptonShutter_auto 1
#define leptonShutter_none 2
#define leptonShutter_autoRAD 3

//Hardware diagnostic bit codes
#define diag_spot 0
#define diag_display 1
#define diag_camera 2
#define diag_touch 3
#define diag_sd 4
#define diag_bat 5
#define diag_lep_conf 6
#define diag_lep_data 7
#define diag_ok 255

//Calibration
#define cal_warmup 0
#define cal_standard 1
#define cal_stdSlope 0.0300f //Standard slope value

//160x120 buffer
uint16_t smallBuffer[4800];

//Array to store one Lepton frame
static byte leptonFrame[164];

enum LeptonReadError
{
  NONE,
  DISCARD,
  SEGMENT_ERROR,
  ROW_ERROR,
  SEGMENT_INVALID
};

byte diagnostic;
byte leptonVersion;
byte leptonShutter;

bool autoMode;
bool limitsLocked;

//Vertical display rotation
bool rotationVert = false;
bool rotationHorizont = false;

//Calibration offset
float calOffset;
//Calibration slope
float calSlope;
//Calibration status
byte calStatus;
//Calibration compensation
float calComp;
//Calibration warmup timer
long calTimer;

void initSPI()
{
  pinMode(pin_lepton_cs, OUTPUT);
  digitalWrite(pin_lepton_cs, HIGH);

  SPI.begin();
}

/* Inits the I2C Bus */
void initI2C()
{
  //Start the Bus
  Wire.begin();
  //Enable Timeout for Hardware start
  Wire.setDefaultTimeout(1000);
  //Use external pullups for new HW

  Wire.pinConfigure(I2C_PINS_18_19, I2C_PULLUP_EXT);
}

/* Switch the SPI clockline to pin 14 */

void startAltClockline(boolean sdStart)
{
  CORE_PIN13_CONFIG = PORT_PCR_MUX(1);
  CORE_PIN14_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
}

/* Switch the SPI clockline back to pin 13 */
void endAltClockline()
{
  CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
  CORE_PIN14_CONFIG = PORT_PCR_MUX(1);
}

/* Checks the specific device from the diagnostic variable */
bool checkDiagnostic(byte device)
{
  //Returns false if the device does not work
  return (diagnostic >> device) & 1;
}

/* Sets the status of a specific device from the diagnostic variable */
void setDiagnostic(byte device)
{
  diagnostic &= ~(1 << device);
}


void lepton_setReg(byte reg)
{
  Wire.beginTransmission(0x2A);
  Wire.write(reg >> 8 & 0xff);
  Wire.write(reg & 0xff);
  Wire.endTransmission();
}

/* Read I2C Register on the lepton */
int lepton_readReg(byte reg)
{
  uint16_t reading;
  lepton_setReg(reg);
  Wire.requestFrom(0x2A, 2);
  reading = Wire.read();
  reading = reading << 8;
  reading |= Wire.read();
  return reading;
}

/* Checks the Lepton hardware revision */
void lepton_version()
{
  //Get AGC Command
  Wire.beginTransmission(0x2A);
  Wire.write(0x00);
  Wire.write(0x04);
  Wire.write(0x48);
  Wire.write(0x1C);
  byte error = Wire.endTransmission();

  //Lepton I2C error, set diagnostic
  if (error != 0)
  {
    setDiagnostic(diag_lep_conf);
    leptonVersion = leptonVersion_2_0_noShutter;
    return;
  }

  //Transfer the new package
  Wire.beginTransmission(0x2A);
  while (lepton_readReg(0x2) & 0x01)
    ;
  Wire.requestFrom(0x2A, lepton_readReg(0x6));
  char leptonhw[33];
  Wire.readBytes(leptonhw, 32);
  Wire.endTransmission();

  //Detected Lepton2 Non-Shuttered
  if (strstr(leptonhw, "05-060340") != NULL)
  {
    leptonVersion = leptonVersion_2_0_noShutter;
    leptonShutter = leptonShutter_none;
  }

  //Detected Lepton2 Shuttered
  else if (strstr(leptonhw, "05-060950") != NULL)
  {
    leptonVersion = leptonVersion_2_0_shutter;
    leptonShutter = leptonShutter_auto;
  }

  //Detected Lepton2.5 Shuttered (Radiometric)
  else if (strstr(leptonhw, "05-070360") != NULL)
  {
    leptonVersion = leptonVersion_2_5_shutter;
    leptonShutter = leptonShutter_autoRAD;
  }

  //Detected Lepton3 Shuttered
  else if (strstr(leptonhw, "05-070620") != NULL)
  {
    leptonVersion = leptonVersion_3_0_shutter;
    leptonShutter = leptonShutter_auto;
  }

  //Detected Lepton3.5 Shuttered (Radiometric)
  else if (strstr(leptonhw, "05-070170") != NULL)
  {
    leptonVersion = leptonVersion_3_5_shutter;
    leptonShutter = leptonShutter_autoRAD;
  }

  //Detected unknown Lepton2 No-Shutter
  else
  {
    leptonVersion = leptonVersion_2_0_noShutter;
    leptonShutter = leptonShutter_none;
  }
}

/* Start Lepton SPI Transmission */
void lepton_begin()
{
  //Start alternative clock line, except for old HW
  //if (mlx90614Version == mlx90614Version_new)
  startAltClockline(true);

  //For Teensy  3.1 / 3.2 and Lepton3 use this one
  //if ((teensyVersion == teensyVersion_old) && ((leptonVersion == leptonVersion_3_0_shutter) || (leptonVersion == leptonVersion_3_5_shutter)))
  //SPI.beginTransaction(SPISettings(30000000, MSBFIRST, SPI_MODE0));

  //Otherwise use 20 Mhz maximum and SPI mode 1
  //else
  SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE1));

  //Start transfer  - CS LOW
  digitalWrite(pin_lepton_cs, LOW);
}

/* End Lepton SPI Transmission */
void lepton_end()
{
  //End transfer - CS HIGH
  digitalWriteFast(pin_lepton_cs, HIGH);

  //End SPI Transaction
  SPI.endTransaction();

  //End alternative clock line, except for old HW
  //if (mlx90614Version == mlx90614Version_new)
  endAltClockline();
}

/* Init the FLIR Lepton LWIR sensor */
void lepton_init()
{
  //Check the Lepton HW Revision
  lepton_version();

  //For radiometric Lepton, set calibration to done
  if ((leptonVersion == leptonVersion_2_5_shutter) || (leptonVersion == leptonVersion_3_5_shutter))
    calStatus = cal_standard;

  //Otherwise init warmup timer
  else
  {
    //Set the calibration timer
    calTimer = millis();
    //Set calibration status to warmup if not coming from mass storage
    calStatus = cal_warmup;
  }

  //Set the compensation value to zero
  calComp = 0;

  //Activate auto mode
  autoMode = true;
  //Deactivate limits Locked
  limitsLocked = false;

  //Check if SPI works
  lepton_begin();
  do
  {
    SPI.transfer(leptonFrame, 164);
  }
  //Repeat as long as the frame is not valid, equals sync
  while (((leptonFrame[0] & 0x0F) == 0x0F) && ((millis() - calTimer) < 1000));
  lepton_end();

  //If sync not received after a second, set diagnostic
  if ((leptonFrame[0] & 0x0F) == 0x0F)
    setDiagnostic(diag_lep_data);
}

void lepton_reset()
{
  lepton_end();
  delay(186);
  lepton_begin();
}

/* Get one line package from the Lepton */
LeptonReadError lepton_getPackage(byte line, byte seg)
{
  //Receive one frame over SPI
  SPI.transfer(leptonFrame, 164);

  //Repeat as long as the frame is not valid, equals sync
  if ((leptonFrame[0] & 0x0F) == 0x0F)
  {
    //Serial.print("Discard error\n");
    return DISCARD;
  }

  //Check if the line number matches the expected line
  if (leptonFrame[1] != line)
  {
    //Serial.print("ROW_Error \n");
    return ROW_ERROR;
  }

  //Everything worked
  return NONE;
}

/* Store one package of 80 columns into RAM */
bool savePackage(byte line, byte segment)
{
  //Go through the video pixels for one video line
  for (int column = 0; column < 80; column++)
  {
    //Apply horizontal mirroring
    if (rotationHorizont)
      column = 79 - column;

    //Make a 16-bit rawvalue from the lepton frame
    uint16_t result = (uint16_t)(leptonFrame[2 * column + 4] << 8 | leptonFrame[2 * column + 5]);

    //Discard horizontal mirroring
    if (rotationHorizont)
      column = 79 - column;

    //Invalid value, return
    if (result == 0)
      return 0;

    //Lepton2
    //Non-rotated
    //Rotated or old hardware version
    smallBuffer[(line * 80) + column] = result;
    //Serial.print("data save done\n");
  }

  //Everything worked
  //Serial.print("savePackage End\n");
  return 1;
}

/* Get one frame of raw values from the lepton */
void lepton_getRawValues()
{
  //Serial.print("Start getRawValues");
  byte line, error, segmentNumbers;

  segmentNumbers = 1;

  //Begin SPI Transmission
  lepton_begin();

  //Go through the segments
  for (byte segment = 1; segment <= segmentNumbers; segment++)
  {
    //Reset error counter for each segment
    error = 0;

    //Go through one segment, equals 60 lines of 80 values
    do
    {
      for (line = 0; line < 60; line++)
      {
        //Maximum error count
        if (error == 255)
        {
          //Reset segment
          segment = 1;
          //Reset error
          error = 0;
          //Reset Lepton SPI
          lepton_reset();
          //Restart at line 0
          break;
        }

        //Get a package from the lepton
        LeptonReadError retVal = lepton_getPackage(line, segment);

        //If everythin worked, continue
        if (retVal == NONE)
          if (savePackage(line, segment))
            continue;

        //Raise lepton error
        error++;
        //Serial.printf("Error %d\n", error);

        //Stabilize framerate
        uint32_t time = micros();
        while ((micros() - time) < 800)
          __asm__ volatile("nop");

        //Restart at line 0
        break;
      }
    } while (line != 60);
  }

  //End SPI Transmission
  //Serial.print("End getRawValue\n");
  lepton_end();
}

// Variables
char sync = 0;

int idx_x = 0;
int idx_y = 0;

void setup()
{
  // Init Hardware
  //Serial.begin(2000000);
  Serial.begin(115200);
  initSPI();

  initI2C();
  Wire.setDefaultTimeout(0);
  //initBuffer();
  lepton_init();

  delay(200);
}

void loop()
{
  usb_serial_flush_input();
  sync = Serial.read();
  usb_serial_flush_output();

  if (sync == 'A')
  {
    lepton_getRawValues();
    usb_serial_write(smallBuffer, 9600);

    usb_serial_flush_output();
  }

}

Ubuntu 16.04 (My laptop) - Using Pyserial
Code:
import numpy as np
import serial
import cv2

cv2.useOptimized()
cv2.useOpenVX()

np.set_printoptions(threshold=np.nan)

ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1)

char_data = 'A'
sync_data = str.encode(char_data)

exit_flag = 0

ser.write(sync_data)
ser.reset_input_buffer()

while 1:

    # Get data from MCU
    buffer = ser.read(9600)

    # Save data numpy format and reshape the data
    lepton = np.frombuffer(buffer, dtype=np.uint16)

    if lepton.size == 0:
        print("Shutter")
        continue

    lepton = lepton.reshape(60, 80)

    ser.reset_input_buffer()
    ser.reset_output_buffer()

    lepton_img = cv2.normalize(lepton, lepton,
                               alpha=0, beta=255,
                               norm_type=cv2.NORM_MINMAX,
                               dtype=cv2.CV_8UC1)

    lepton_img = cv2.resize(lepton_img, None, None, fx=4, fy=4,
                            interpolation=cv2.INTER_CUBIC)

    cv2.imshow("Test", lepton_img)
    ser.reset_input_buffer()

    if cv2.waitKey(1) & 0xFF == ord('q'):
        exit_flag = 1
        break

    ser.write(sync_data)
    ser.reset_input_buffer()

print("End")
ser.reset_input_buffer()

Teensy get 9600 byte from Lepton2.5(Flir IR Camera) and send this data my laptop.
but my laptop can't receive data from teensy (Using usb serial)
(Receive nothing, so python program print "Shutter")

all configuration is fine, Teensy was connect correctly "ttyACM0" and other example code (blink, serial "Hello World") is working good.

i don't know why this is not work..
(The odd thing is sometimes all work fine.. i don't know why....)

Need help :(
 
Last edited:
Not clear - have the udev rules been applied? Does the "Hello World" print to a Serial Monitor? Repeatedly for a long time?

Not a Linux user - but IIRC there was a note once that Teensy might connect for a short time - then that port is overtaken by another background 'modem' app?

If you try the sketch posted here can that be programmed and have the prints persist to SerMon and have the SerMon 'Send' data and have it printed back? When that works try to connect with Python to test the same perhaps.
 
why are you polling and flushing like that? Not necessary. Should get a basic print setup working first then work on the handling after :)
 
Not clear - have the udev rules been applied? Does the "Hello World" print to a Serial Monitor? Repeatedly for a long time?
Yes, I applied this correctly

Not a Linux user - but IIRC there was a note once that Teensy might connect for a short time - then that port is overtaken by another background 'modem' app?
Any other program don't use this usb port(which is teensy use)

If you try the sketch posted here can that be programmed and have the prints persist to SerMon and have the SerMon 'Send' data and have it printed back? When that works try to connect with Python to test the same perhaps.
Screenshot from 2018-06-04 14-26-38.jpg
I run sketch, work fine..
 
Pretty sure at least one of your problems is this:

Code:
  usb_serial_flush_input();
  sync = Serial.read();

Calling usb_serial_flush_input() discards any received data. So when you immediately call Serial.read(), you're virtually sure the "sync" will get -1, meaning no data has arrived. That elapsed time is so very small that the odds of incoming USB data arriving are extremely thin, like trying to win the Lottery with 1 ticket. The rest of your program never runs because you always discard the commands from your PC.
 
Status
Not open for further replies.
Back
Top