So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By gola001
#94609 Hi
I'm trying to read data from my mitutoyo height gauge using the following code:

Code: Select all// Derived from https://www.instructables.com/id/Interfacing-a-Digital-Micrometer-to-a-Microcontrol/
#include <SPI.h>
#include <Wire.h>

#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


// When defined, will send SPC data as hexadecimal over serial.
#define HEX_DATA_OUTPUT

// When defined, will convert raw data to human readable string
// and send over serial.
#define HUMAN_READABLE_OUTPUT

int req = 5; //Arduino pin for REQ line, drives transistor to ground SPC port pin 5 (~REQ)
int dat = 2; //Arduino pin for Data line, connects directly to SPC port pin 2 (DATA)
int clk = 3; //Arduino pin for Clock line, connects directly to SPC port pin 3 (~CLK)

int i = 0;
int j = 0;
int k = 0;

// Mitutoyo SPC data port transmits 13 4-bit values
// Byte Meaning
// 0    Header, always 0xF
// 1    Header, always 0xF
// 2    Header, always 0xF
// 3    Header, always 0xF
// 4    Sign. Zero is positive. 0x8 is negative.
// 5    Most significant digit (MSD) of measurement
// 6    Next digit of measurement
// 7    Next digit of measurement
// 8    Next digit of measurement
// 9    Next digit of measurement
// 10   Least significant digit (LSD) of measurement
// 11   Digit to place decimal point
// 12   Unit. Zero is mm. Nonzero (b1000 is 1?) is inch

byte spcdata[13]; // The raw data sent by instrument

#ifdef HUMAN_READABLE_OUTPUT
float value;      // The value calculated from raw data
int decimal;      // Number of digits that are after decimal point
#endif

void setup() {
    Serial.begin(9600);
    pinMode(req, OUTPUT);
    pinMode(clk, INPUT_PULLUP);
    pinMode(dat, INPUT_PULLUP);
    digitalWrite(req,LOW); // set request at high
   
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  // Clear the buffer
  display.clearDisplay();
  display.setTextSize(3); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
 

}

void loop() {
  getData();
#ifdef HEX_DATA_OUTPUT
    for( i = 0; i < 13; i++ ) {
        Serial.print(spcdata[i],HEX);
    }
#ifdef HUMAN_READABLE_OUTPUT
    // Need a separator if we're printing human readable as well
    Serial.print(" ");
#endif // HUMAN_READABLE_OUTPUT
#endif //HEX_DATA_OUTPUT

#ifdef HUMAN_READABLE_OUTPUT
    // Combine measurement digits into a number
    value = 0;
    for( i = 5; i <= 10; i++) {
        value *= 10;
        value += spcdata[i];
    }

    // Adjust number for decimal point position
    decimal = spcdata[11];
    value /= pow(10,decimal);

    // Adjust if number is negative
    if (spcdata[4] == 0x8) {
        value *= -1;
    }
    // Print resulting value to serial port, to specified
    // number of digits after decimal point.
    display.clearDisplay();
    display.setCursor(0, 0);
    Serial.print(value,decimal);
    display.println(value,decimal);
    // Append units for value
    if (spcdata[12] == 0) {
        Serial.print(" mm");
        display.print(" mm");       
    } else {
        Serial.print(" in");
        display.print(" in");
    }
       display.display();      // Show initial text
#endif // HUMAN_READABLE_OUTPUT

    Serial.println();
   
}

void getData(void){
    digitalWrite(req, HIGH); // generate set request

    for( i = 0; i < 13; i++ ) {
        k = 0;

        // Timing diagram indicates data bit has been valid for about 120
        // microseconds before the clock signal is raised, and remains
        // valid for about 120 microseconds afterwards. This code reads data
        // bit at the falling clock edge.
        for (j = 0; j < 4; j++) {
            while( digitalRead(clk) == LOW) {
            } // hold until clock is high
            while( digitalRead(clk) == HIGH) {
            } // hold until clock is low
            bitWrite(k, j, (digitalRead(dat) & 0x1));
        }

        // After reading the first 4-bit value, we can drop REQ output.
        if (i == 0) {
            digitalWrite(req,LOW);
        }
        spcdata[i] = k;
    }
}


but whenever I upload the code on my NODEMCU, it crashes every few seconds with a soft WDT reset message. Can anyone please help me why that is?

Thanks in advance!
User avatar
By QuickFix
#94630 The code you're using is for an ATMEL Arduino board, an ESP8266 is NOT an ATMEL; the fact that you can program an ESP using the Arduino IDE doesn't mean everything works directly out of the box. :idea:

The ESP has a WiFi stack (see it as a second process running alongside yours) that needs to update every once in a while. If you have tight loops, the WiFi stack can get choked, resulting in a watchdog trigger reset (or "WDT").

The solution is to make your Arduino code ESP8266 compatible by adding a delay(0) or yield() into all tight loops that might lock up the code.

For a more in-depth explanation of the problem, have a read through this article. :idea: