[SOLVED] Problem with migrating sketch from Arduino to Particle

I have this code, which works perfectly on my Arduino.
It also verifies online on the particle website, but when I upload to my Photon, it crashes and keeps blinking green.

Any hints or help on how to tackle the problem?

/***************************************************
  Thermistor Calibration
 
  Find the Steinhart-Hart equation coefficients for a thermistor.
  
  See video of calibration here: http://www.youtube.com/watch?v=5qDVmvCPNdQ
  
  Copyright 2013 Tony DiCola (tony@tonydicola.com).
  Released under an MIT license: 
    http://opensource.org/licenses/MIT
  
 ****************************************************/

#include <math.h>

int THERMISTOR_PIN = A0;           // Pin between the thermistor and series resistor.
int SERIES_RESISTOR = 10000;        // Series resistor value in ohms.
int ADC_SAMPLES = 5;                // Number of ADC samples to average when taking a reading

// Temperature unit conversion functions and state.
typedef float (*TempConversion)(float);
TempConversion ToKelvin; 
TempConversion FromKelvin;
char* TempUnit;

// Steinhart-Hart coefficients.
float A, B, C;

void setup(void) {
  Serial.begin(115200);
  
  ToKelvin = &celsiusToKelvin;
  FromKelvin = &kelvinToCelsius;
  TempUnit = "Celsius";
  
  Serial.println(F("Thermistor probe coefficient calibration"));
  Serial.println(F("----------------------------------------\n"));
  
  Serial.println(F("To perform this calibration you will need:\n - A thermometer\n - Glass of ice water\n - Glass of luke-warm water\n - Glass of hot water"));
  
  Serial.println(F("\nSTEP ONE:"));
  Serial.println(F("Put the thermistor probe and thermometer into the ice water.\n"));
  
  waitForOk();
  
  printTempMessage();
  
  float T1 = waitForFloat();
  float R1 = readResistance();
  
  Serial.print("Got temperature value: "); Serial.println(T1, 3);
  
  Serial.println(F("\nSTEP TWO:"));
  Serial.println(F("Put the thermistor probe and thermometer into the luke-warm water.\n"));

  waitForOk();
  
  printTempMessage();
  
  float T2 = waitForFloat();
  float R2 = readResistance();
  
  Serial.print("Got temperature value: "); Serial.println(T2, 3);
  
  Serial.println(F("\nSTEP THREE:"));
  Serial.println(F("Put the thermistor probe and thermometer into the hot water.\n"));
  
  waitForOk();
  
  printTempMessage();
  
  float T3 = waitForFloat();
  float R3 = readResistance();
  
  Serial.print("Got temperature value: "); Serial.println(T3, 3);
  
  Serial.println(F("\n----------------------------------------\n"));
  
  Serial.println(F("Calibration complete!\n"));
  
  // Solve system of equations to determine coefficients for Steinhart-Hart equation.
  // See: http://en.wikipedia.org/wiki/Steinhart%E2%80%93Hart_equation
  float L1 = log(R1);
  float L2 = log(R2);
  float L3 = log(R3);
  float Y1 = 1.0 / ToKelvin(T1);
  float Y2 = 1.0 / ToKelvin(T2);
  float Y3 = 1.0 / ToKelvin(T3);
  float gamma2 = ((Y2 - Y1)/(L2 - L1));
  float gamma3 = ((Y3 - Y1)/(L3 - L1));
  C = ((gamma3 - gamma2)/(L3 - L2))*pow((L1 + L2 + L3), -1.0);
  B = gamma2 - C*(pow(L1, 2.0) + L1*L2 + pow(L2, 2.0));
  A = Y1 - (B + pow(L1, 2.0)*C)*L1;
  
  Serial.println(F("Use these three coefficients in your thermistor sketch:"));
  Serial.print("Coefficient A = "); Serial.println(A, 12);
  Serial.print("Coefficient B = "); Serial.println(B, 12);
  Serial.print("Coefficient C = "); Serial.println(C, 12);
  
  Serial.println(F("\nNow the temperature of the thermistor"));
  Serial.println(F("will be displayed every second.\n"));
  
  waitForOk();
  
  Serial.println(F(""));
}

void loop(void) {
  float temp = FromKelvin(readTemp());
  Serial.print(F("Temperature: ")); Serial.print(temp); Serial.print(F(" in ")); Serial.println(TempUnit);
  delay(1000);
}

void waitForOk() {
  Serial.println(F("Type OK <enter> to continue.\n"));
  while (!(Serial.findUntil("OK", "\n")));
}

float waitForFloat() {
  while (!(Serial.available() > 0));
  return Serial.parseFloat();
}

void printTempMessage() {
  Serial.println(F("Wait about 30 seconds for the thermistor to stabilize then,"));
  Serial.print(F("type the water temperature (in ")); Serial.print(TempUnit); Serial.println(F(") and press <enter>.\n"));
}

double readResistance() {
  float reading = 0;
  for (int i = 0; i < ADC_SAMPLES; ++i) {
    reading += analogRead(THERMISTOR_PIN);
  }
  reading /= (float)ADC_SAMPLES;
  reading = (4096 / reading) - 1;
  return SERIES_RESISTOR / reading;
}

float kelvinToFahrenheit(float kelvin) {
  return kelvin*(9.0/5.0) - 459.67;
}

float fahrenheitToKelvin(float fahrenheit) {
  return (fahrenheit + 459.67)*(5.0/9.0);
}

float kelvinToCelsius(float kelvin) {
  return kelvin - 273.15;
}

float celsiusToKelvin(float celsius) {
  return celsius + 273.15; 
}

float readTemp() {
  float R = readResistance();
  float kelvin = 1.0/(A + B*log(R) + C*pow(log(R), 3.0));
  return kelvin;
}

I cannot recall if the Particle team accomodated Arduino’s F macro, but you could add this to the top of your file (or get rid of the F macro in the serial prints).

#define F(x) x

it took that to get it to verify for me!

@Boye, @BulldogLowell, the F macro is implemented and thus the reason the code compiled.

This indicates that there is blocking code causing a loss of cloud connection and most likely more. Is it flashing green or breathing green?

Looking at the code, it is easy to spot Arduino code since it is full of blocking calls. For example ‘waitForOK()’ has a while() statement which waits for data on the Serial (USB) port. It will time out after 2 seconds if the text is not found. Also, waitForFloat blocks forever waiting on Serial data as well. In short, the code needs to be adapted for Particle!

One way to help is to add SYSTEM_THREAD(ENABLED); just after the #include <math>; statement. This will allow the system firmware to run independently of the user thread so that blocking code in the user thread doesn’t kill wifi or cloud connections. The rest would need a lot more explanation. Give that a shot and let us know how it works. :grinning:

3 Likes

So I added SYSTEM_THREAD(ENABLED); removed the F macro and added a delay at the beginning, and now nearly working. The Photon does not crash or loose connection, and I am able to see and input text in the serial window.

The only problem now, is I cannot get the last lines to verify. The ones I commented out.

/***************************************************
  Thermistor Calibration
 
  Find the Steinhart-Hart equation coefficients for a thermistor.
  
  See video of calibration here: http://www.youtube.com/watch?v=5qDVmvCPNdQ
  
  Copyright 2013 Tony DiCola (tony@tonydicola.com).
  Released under an MIT license: 
    http://opensource.org/licenses/MIT
  
 ****************************************************/

#include <math.h>
SYSTEM_THREAD(ENABLED);

int THERMISTOR_PIN = A0;        // Pin between the thermistor and series resistor.
int SERIES_RESISTOR = 10000;    // Series resistor value in ohms.
int ADC_SAMPLES = 5;            // Number of ADC samples to average when taking a reading

// Temperature unit conversion functions and state.
typedef float (*TempConversion)(float);
TempConversion ToKelvin; 
TempConversion FromKelvin;
char* TempUnit;

// Steinhart-Hart coefficients.
float A, B, C;

void setup(void) {
    Serial.begin(115200);
    delay(5000);
  
    ToKelvin = &celsiusToKelvin;
    FromKelvin = &kelvinToCelsius;
    TempUnit = "Celsius";
  
    Serial.println("Thermistor probe coefficient calibration");
    Serial.println("----------------------------------------\n");
  
    Serial.println("To perform this calibration you will need:\n - A thermometer\n - Glass of ice water\n - Glass of luke-warm water\n - Glass of hot water");
  
    Serial.println("\nSTEP ONE:");
    Serial.println("Put the thermistor probe and thermometer into the ice water.\n");
  
    waitForOk();
  
    printTempMessage();
  
    float T1 = waitForFloat();
    float R1 = readResistance();
  
    Serial.print("Got temperature value: "); Serial.println(T1, 3);
  
    Serial.println("\nSTEP TWO:");
    Serial.println("Put the thermistor probe and thermometer into the luke-warm water.\n");

    waitForOk();
  
    printTempMessage();


    float T2 = waitForFloat();
    float R2 = readResistance();
  
    Serial.print("Got temperature value: "); Serial.println(T2, 3);
  
    Serial.println("\nSTEP THREE:");
    Serial.println("Put the thermistor probe and thermometer into the hot water.\n");
  
    waitForOk();
  
    printTempMessage();
  
    float T3 = waitForFloat();
    float R3 = readResistance();
  
    Serial.print("Got temperature value: "); Serial.println(T3, 3);
  
    Serial.println("\n----------------------------------------\n");
  
    Serial.println("Calibration complete!\n");

  
    // Solve system of equations to determine coefficients for Steinhart-Hart equation.
    // See: http://en.wikipedia.org/wiki/Steinhart%E2%80%93Hart_equation
    float L1 = log(R1);
    float L2 = log(R2);
    float L3 = log(R3);
    float Y1 = 1.0 / ToKelvin(T1);
    float Y2 = 1.0 / ToKelvin(T2);
    float Y3 = 1.0 / ToKelvin(T3);
    float gamma2 = ((Y2 - Y1)/(L2 - L1));
    float gamma3 = ((Y3 - Y1)/(L3 - L1));
    C = ((gamma3 - gamma2)/(L3 - L2))*pow((L1 + L2 + L3), -1.0);
    B = gamma2 - C*(pow(L1, 2.0) + L1*L2 + pow(L2, 2.0));
    A = Y1 - (B + pow(L1, 2.0)*C)*L1;
  
    Serial.println("Use these three coefficients in your thermistor sketch:");
    Serial.print("Coefficient A = "); Serial.println(A, 12);
    Serial.print("Coefficient B = "); Serial.println(B, 12);
    Serial.print("Coefficient C = "); Serial.println(C, 12);
  
    Serial.println("\nNow the temperature of the thermistor");
    Serial.println("will be displayed every second.\n");
  
    waitForOk();
  
    Serial.println("");
}

void loop(void) {
    //float temp = FromKelvin(readTemp());
    Serial.print("Temperature: "); 
    //Serial.print(temp); 
    Serial.print(" in "); 
    Serial.println(TempUnit);
    delay(1000);
}

void waitForOk() {
    Serial.println("Type OK <enter> to continue.\n");
    while (!(Serial.findUntil("OK", "\n")));
}


float waitForFloat() {
    while (!(Serial.available() > 0));
    return Serial.parseFloat();
}


void printTempMessage() {
    Serial.println("Wait about 30 seconds for the thermistor to stabilize then,");
    Serial.print("type the water temperature (in "); 
    Serial.print(TempUnit); 
    Serial.println(") and press <enter>.\n");
}

double readResistance() {
    float reading = 0;
    for (int i = 0; i < ADC_SAMPLES; ++i) {
        reading += analogRead(THERMISTOR_PIN);
    }
    reading /= (float)ADC_SAMPLES;
    reading = (4096 / reading) - 1;
    return SERIES_RESISTOR / reading;
}

float kelvinToFahrenheit(float kelvin) {
    return kelvin*(9.0/5.0) - 459.67;
}

float fahrenheitToKelvin(float fahrenheit) {
    return (fahrenheit + 459.67)*(5.0/9.0);
}

float kelvinToCelsius(float kelvin) {
    return kelvin - 273.15;
}

float celsiusToKelvin(float celsius) {
    return celsius + 273.15; 
}

float readTemp() {
    float R = readResistance();
    float kelvin = 1.0/(A + B*log(R) + C*pow(log(R), 3.0));
    return kelvin;
}

/*
float fahrenheitToKelvin(float fahrenheit) {
  return (fahrenheit + 459.67)*(5.0/9.0);
}

float kelvinToCelsius(float kelvin) {
  return kelvin - 273.15;
}

float celsiusToKelvin(float celsius) {
  return celsius + 273.15; 
}

float readTemp() {
  float R = readResistance();
  float kelvin = 1.0/(A + B*log(R) + C*pow(log(R), 3.0));
  return kelvin;
} */

Providing the error messages along with the " I cannot get the last lines to verify." would help :wink:

A wild guess would be that you have all these functions implemented twice!

2 Likes

It was impressive that I did not see that… The program works fine now, thanks for the help :smile:
I will remember the error messages next time.

1 Like

@peekay123 @ScruffR @BulldogLowell Thank you all for the help!

1 Like