0

Help: Using Feather M4 Express with Serial and SPI
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Help: Using Feather M4 Express with Serial and SPI

by andygravity on Tue Jan 29, 2019 4:17 pm

I am trying to use the Feather M4 Express with a laser rangefinder (datasheet attached) that communicates over serial. I have the RX and TX pins of the laser connected to the Feather's TX and RX pins respectively and the OLED screen attached to the hardware SPI and using pins 11, 12, and 13 for DC, CS, and RESET respectively. I know the screen works independently, as I am able to run a Hello World program to print to it on the Feather.

I am not seeing any data from the laser printed to the screen. I don't know if I am using Serial correctly on the Feather (the variants.cpp file and the information on the forum helped a little, but not by much), but I know the code works on an Arduino Uno using SoftwareSerial and software SPI. The code that I am trying to run is shown below. Would anyone have any ideas for troubleshooting? Am I using the hardware serial pins on the Feather M4 correctly in my code?

Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include <Wire.h>

#define OLED_DC 11
#define OLED_CS 12
#define OLED_RESET 13
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, OLED_DC, OLED_RESET, OLED_CS);

// volatile bool saveBtn = false;

void setup() {
  Serial.begin(19200);
 
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }
 
  Serial1.begin(19200);
  Serial1.write('F');
}

void loop() {
  freeMeasure();

}

void freeMeasure() {
  // Define screen position values
  const byte FMtitle[] = {1, 1}; // [column, row]
  const byte distanceOut[] = {1, 3};
  const byte units[] = {19, 3};
  const byte saveText[] = {17, 8};
  const byte lastSaveText[] = {1, 5};

  // Variables needed for function to run. Can't call in while loop or they would reset their values each time,
  //  which we dont want.
  float value;
  float prevValue;
  int saveCount = 0;
  // bool prevSaveBtn = saveBtn;

  while (true) {
    // Clear the display and get the distance value
    value = getDistance();
    display.clearDisplay();
    display.setTextColor(WHITE);
    display.setTextSize(1);
    display.cp437(true);

    // Display the title
    display.setCursor(col2Pixel(FMtitle[0]), row2Pixel(FMtitle[1]));
    display.print(F("Free Measure"));

    // Display previously saved measurement
    // Display "--.--" for last saved measurement
    display.setCursor(col2Pixel(lastSaveText[0]), row2Pixel(lastSaveText[1]));
    display.print(F("LAST SAVED:"));

//    // Display Save button
//    // If the save button is pressed, save the measurement to the SD card and show on the screen
//    // TODO: Add a save button
//
//    if (saveBtn != prevSaveBtn) {
//      // Button has either been pressed or released
//      prevValue = value;
//      saveCount = saveCount + 1;
//      // Save value when button is released
//
//
//      // String to save to SD card. Not used at the moment
//      //        String dataString = "";
//      //        dataString += String(saveCount);
//      //        dataString += ",";
//      //        dataString += String(savedDist);
//
//      // Save this string to the SD card
//
//
//      display.setCursor(col2Pixel(saveText[0]), row2Pixel(saveText[1]));
//      display.setTextColor(BLACK, WHITE); // Set inverted
//      display.print("SAVE");
//      display.setTextColor(WHITE);
//    } else {
//      display.setCursor(col2Pixel(saveText[0]), row2Pixel(saveText[1]));
//      display.setTextColor(WHITE);
//      display.print("SAVE");
//    }
//    prevSaveBtn = saveBtn;

    display.setCursor(col2Pixel(lastSaveText[0] + 11), row2Pixel(lastSaveText[1]));
    display.print(saveCount);
    if (saveCount == 0) {
      display.print(F(": --.--"));
    } else {
      display.print(F(":"));
      display.print(prevValue, 1);
      display.print(F("cm"));
    }

    // Display measurement to screen
    display.setCursor(col2Pixel(distanceOut[0]), row2Pixel(distanceOut[1]));
    display.print(value, 2);
    display.print(F("cm"));
    display.display();
    //delay(100);
  }
}

uint8_t row2Pixel(uint8_t row) {
  if (row > 8 || row < 0) {
    // Error
    return 0;
  } else {
    return (row * 8) - 8;
  }
}

uint8_t col2Pixel(uint8_t col) {
  if (col > 21 || col < 0) {
    // Error
    return 0;
  } else {
    return (col * 6) - 6;
  }
}

float getDistance() {
  Serial1.setTimeout(500);
  Serial1.write('F');
  String mess = "";
  float X = 0.0;
  char c, d ;

  bool flag = false;
  //digitalWrite(7,HIGH);
  //this code stops when device is turned off
  while (X >= 3000.0 || X <= 0.0) {
    Serial.println(F("\nBegin reading"));
    String str = Serial1.readStringUntil(':');
    Serial.println(str);
    int n = 0;
    //Serial.println("ture");

    Serial.println("-------");

    while (n < 8) {
      c = Serial1.read();
      Serial.print(c);
      mess = mess + c;

      n = n + 1;
      delay(1);
    }
    X = (mess.toFloat()) * 100;

    Serial.println(mess);
    Serial.println(X);
    if (X == 0.0 || X >= 3000.0) {
      X = 0.0000001;
    }
    String str2 = Serial1.readString();
    Serial.println(str2);
  }
  digitalWrite(7, LOW);
  return X;

}
Attachments
703A user manual.pdf
(1.49 MiB) Downloaded 6 times

andygravity
 
Posts: 4
Joined: Mon Jan 21, 2019 4:16 pm

Re: Help: Using Feather M4 Express with Serial and SPI

by andygravity on Fri Feb 15, 2019 11:43 am

SOLVED

The variants.cpp file (located in C:/Users/"USERNAME"/AppData/Local/Arduino15/packages/adafruit/hardware/samd/1.2.9/variants/feather_m4/variants.cpp) defined Serial1 as a UART port using the serial hardware pins on the Feather M4 Express:

Code: Select all | TOGGLE FULL SIZE
Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;

This meant that, to access those pins, I just needed to use #define to reference the hardware serial pins:

Code: Select all | TOGGLE FULL SIZE
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #include <SPI.h>
    #include <Wire.h>

    #define OLED_DC 11
    #define OLED_CS 12
    #define OLED_RESET 13
    #define SCREEN_WIDTH 128
    #define SCREEN_HEIGHT 64

    #define LaserSerial Serial1
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, OLED_DC, OLED_RESET, OLED_CS);

    // volatile bool saveBtn = false;

    void setup() {
      Serial.begin(19200);
     
      // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
      if (!display.begin(SSD1306_SWITCHCAPVCC)) {
        Serial.println(F("SSD1306 allocation failed"));
        for (;;); // Don't proceed, loop forever
      }
     
      LaserSerial.begin(19200);
      LaserSerial.write('F');
    }

    void loop() {
      freeMeasure();

    }

    void freeMeasure() {
      // Define screen position values
      const byte FMtitle[] = {1, 1}; // [column, row]
      const byte distanceOut[] = {1, 3};
      const byte units[] = {19, 3};
      const byte saveText[] = {17, 8};
      const byte lastSaveText[] = {1, 5};

      // Variables needed for function to run. Can't call in while loop or they would reset their values each time,
      //  which we dont want.
      float value;
      float prevValue;
      int saveCount = 0;
      // bool prevSaveBtn = saveBtn;

      while (true) {
        // Clear the display and get the distance value
        value = getDistance();
        display.clearDisplay();
        display.setTextColor(WHITE);
        display.setTextSize(1);
        display.cp437(true);

        // Display the title
        display.setCursor(col2Pixel(FMtitle[0]), row2Pixel(FMtitle[1]));
        display.print(F("Free Measure"));

        // Display previously saved measurement
        // Display "--.--" for last saved measurement
        display.setCursor(col2Pixel(lastSaveText[0]), row2Pixel(lastSaveText[1]));
        display.print(F("LAST SAVED:"));

    //    // Display Save button
    //    // If the save button is pressed, save the measurement to the SD card and show on the screen
    //    // TODO: Add a save button
    //
    //    if (saveBtn != prevSaveBtn) {
    //      // Button has either been pressed or released
    //      prevValue = value;
    //      saveCount = saveCount + 1;
    //      // Save value when button is released
    //
    //
    //      // String to save to SD card. Not used at the moment
    //      //        String dataString = "";
    //      //        dataString += String(saveCount);
    //      //        dataString += ",";
    //      //        dataString += String(savedDist);
    //
    //      // Save this string to the SD card
    //
    //
    //      display.setCursor(col2Pixel(saveText[0]), row2Pixel(saveText[1]));
    //      display.setTextColor(BLACK, WHITE); // Set inverted
    //      display.print("SAVE");
    //      display.setTextColor(WHITE);
    //    } else {
    //      display.setCursor(col2Pixel(saveText[0]), row2Pixel(saveText[1]));
    //      display.setTextColor(WHITE);
    //      display.print("SAVE");
    //    }
    //    prevSaveBtn = saveBtn;

        display.setCursor(col2Pixel(lastSaveText[0] + 11), row2Pixel(lastSaveText[1]));
        display.print(saveCount);
        if (saveCount == 0) {
          display.print(F(": --.--"));
        } else {
          display.print(F(":"));
          display.print(prevValue, 1);
          display.print(F("cm"));
        }

        // Display measurement to screen
        display.setCursor(col2Pixel(distanceOut[0]), row2Pixel(distanceOut[1]));
        display.print(value, 2);
        display.print(F("cm"));
        display.display();
        //delay(100);
      }
    }

    uint8_t row2Pixel(uint8_t row) {
      if (row > 8 || row < 0) {
        // Error
        return 0;
      } else {
        return (row * 8) - 8;
      }
    }

    uint8_t col2Pixel(uint8_t col) {
      if (col > 21 || col < 0) {
        // Error
        return 0;
      } else {
        return (col * 6) - 6;
      }
    }

    float getDistance() {
      LaserSerial.setTimeout(500);
      LaserSerial.write('F');
      String mess = "";
      float X = 0.0;
      char c, d ;

      bool flag = false;
      //digitalWrite(7,HIGH);
      //this code stops when device is turned off
      while (X >= 3000.0 || X <= 0.0) {
        Serial.println(F("\nBegin reading"));
        String str = LaserSerial.readStringUntil(':');
        Serial.println(str);
        int n = 0;
        //Serial.println("ture");

        Serial.println("-------");

        while (n < 8) {
          c = LaserSerial.read();
          Serial.print(c);
          mess = mess + c;

          n = n + 1;
          delay(1);
        }
        X = (mess.toFloat()) * 100;

        Serial.println(mess);
        Serial.println(X);
        if (X == 0.0 || X >= 3000.0) {
          X = 0.0000001;
        }
        String str2 = LaserSerial.readString();
        Serial.println(str2);
      }
      digitalWrite(7, LOW);
      return X;

    }

andygravity
 
Posts: 4
Joined: Mon Jan 21, 2019 4:16 pm

Please be positive and constructive with your questions and comments.