Cloud Code used to work now not verified

When I verified the cloud code (which used to work fine) now I got this error:

In file included from ../inc/spark_wiring.h:29:0,
from ../inc/application.h:29,
from furby_chat.cpp:2:
../../core-common-lib/SPARK_Firmware_Driver/inc/config.h:12:2: warning: #warning "Defaulting to Release Build" [-Wcpp]
#warning "Defaulting to Release Build"
^
In file included from /opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/char_traits.h:39:0,
from /opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/string:40,
from /opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/stdexcept:39,
from /opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/array:38,
from furby_chat.cpp:3:
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:239:56: error: macro "min" passed 3 arguments, but takes just 2
min(const _Tp& __a, const _Tp& __b, _Compare __comp)
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:260:56: error: macro "max" passed 3 arguments, but takes just 2
max(const _Tp& __a, const _Tp& __b, _Compare __comp)
^
In file included from ../inc/application.h:29:0,
from furby_chat.cpp:2:
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:193:5: error: expected unqualified-id before 'const'
min(const _Tp& __a, const _Tp& __b)
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:193:5: error: expected ')' before 'const'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:193:5: error: expected ')' before 'const'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:193:5: error: expected initializer before 'const'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:216:5: error: expected unqualified-id before 'const'
max(const _Tp& __a, const _Tp& __b)
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:216:5: error: expected ')' before 'const'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:216:5: error: expected ')' before 'const'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:216:5: error: expected initializer before 'const'
In file included from /opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/char_traits.h:39:0,
from /opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/string:40,
from /opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/stdexcept:39,
from /opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/array:38,
from furby_chat.cpp:3:
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:239:5: error: 'std::min' declared as an 'inline' variable
min(const _Tp& __a, const _Tp& __b, _Compare __comp)
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:239:5: error: template declaration of 'const _Tp& std::min'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:242:7: error: expected primary-expression before 'if'
if (__comp(__b, __a))
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:242:7: error: expected '}' before 'if'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:244:7: error: expected unqualified-id before 'return'
return __a;
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:260:5: error: 'max' declared as an 'inline' variable
max(const _Tp& __a, const _Tp& __b, _Compare __comp)
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:260:5: error: template declaration of 'const _Tp& max'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:263:7: error: expected primary-expression before 'if'
if (__comp(__a, __b))
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:263:7: error: expected '}' before 'if'
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:265:7: error: expected unqualified-id before 'return'
return __a;
^
/opt/gcc_arm/arm-none-eabi/include/c++/4.8.4/bits/stl_algobase.h:266:5: error: expected declaration before '}' token
}
^
make: *** [furby_chat.o] Error 1

Which is really hard for me to debug since I was away for some time. All I suspect is there’s some issue with the C++ part.

Here is the code:

#define RANDOM(maxRand) (rand() % maxRand)
#include <array>

// Node server on EC2
TCPClient client;
byte server[] = { 54, 68, 214, 214 };
int port = 8080;

// ISR variables
volatile bool padded = false;
volatile bool poked = false;
volatile bool tilted = false;
volatile bool noisy = false;

// TCPClient buffers
uint8_t giggle[] = {'g', 'i', 'g', 'g', 'l', 'e'};
uint8_t adore[] = {'a', 'd', 'o', 'r', 'a', 'b', 'l', 'e'};
uint8_t whoa[] = {'k', 'n', 'o', 'c', 'k', ' ', 'i', 't', ' ', 'o', 'f', 'f'};
uint8_t loud[] = {'S', 'H', 'O', 'U', 'T'};

// for debounce
long lastPoked = 0;
long lastPadded = 0;
long lastTilted = 0;
long lastNoisy = 0;
long debounceDelay = 10;
long noiseDetectionDelay = 1000;

const int statusPin = D0;
const int pokePin = D1;
const int padPin = D4;
const int tiltPin = D5;
const int noisePin = A1;
const int motorPin = A0;

// the only Spark.function to request
int chat(String word) {
    motor();
    speak(word);
}

void setup() {
    
    pinMode(statusPin, OUTPUT);
    pinMode(pokePin, INPUT_PULLUP);
    pinMode(padPin, INPUT_PULLUP);
    pinMode(tiltPin, INPUT_PULLUP);
    pinMode(noisePin, INPUT_PULLUP);
    pinMode(motorPin, OUTPUT);

    Spark.function("chat", chat);

    // For debugging
    Serial.begin(9600);
    Serial.println("connecting...");
    delay(10);
    Serial.flush();
    
    // For EMIC2
    Serial1.begin(9600);

    delay(3000);
    Serial1.print('\n');
    delay(10);                          
    Serial1.flush();
    Serial1.println();
    // Set volume (-48 to 18)
    Serial1.println("V18");
    // Set voice (0 - 8) (Not available via DECTalk)
    Serial1.println("N4");
    // Set rate (75 - 600)
    Serial1.println("W150");
    // Set Parser (0 = DECTalk, 1 = Epson)
    Serial1.println("P0");
    
    
    attachInterrupt(pokePin, isPoked, FALLING);
    attachInterrupt(padPin, isPadded, FALLING);
    attachInterrupt(tiltPin, isTilted, FALLING);
    
    client.connect(server, 8081);
}

void loop() {
    connectStatus();
    moveAndTalk();
    detectNoise();   
}

void motor() {
    analogWrite(motorPin, 255);
    delay(1500);
    analogWrite(motorPin, 0);
}

// Deal with the byte array
template<std::size_t N>
void sendServer(const uint8_t (&a)[N]) {
    if ( client.connect(server, 8081) ) {
        Serial.println("connected, writing to EC2");
        client.write(a, N);
        delay(500);
        Serial.println("stopping client...");
        client.flush();
        client.stop();
    } else Serial.println("not able to connect");
}

// Trigger movement and sound
void moveAndTalk() {
    /*
    // if noisy is true
    if (noisy) {
        // set noisy to the current clock
        lastNoisy = millis();
        // speak out
        speak("What's that noise?");
        //sendServer(loud);
        noisy = false;
    }
    */
    if ((millis() - lastNoisy) > noiseDetectionDelay) {
        if (noisy) {
            lastNoisy = millis();
            speak("What's that noise?");
            noisy = false;
        }
    }
    
    if (tilted) {
        lastTilted = millis();
    }
    if ((millis() - lastTilted) > debounceDelay) {
        if (digitalRead(tiltPin) == LOW) {
            motor();
            speak("[:pitch 550] Woh [:pitch 250] Aah!");
            sendServer(whoa);
            if (tilted) {
                tilted = !tilted;
            }
        }
    }
    
    // If variable changed due to noise
    if (poked) {
        lastPoked = millis(); // reset the clock to track that
    }
    // Now whatever that was, it's still here after the debounceDelay
    if ((millis() - lastPoked) > debounceDelay) {
        // Well, if the pin is still LOW
        if (digitalRead(pokePin) == LOW) {
            motor();
            speak("[:pitch 550] Wha [:pitch 250] Ha ha ha!");
            sendServer(giggle);
            if (poked) {
                poked = !poked;
            }
        }
    }
    
    // If variable changed due to noise
    if (padded) {
        lastPadded = millis(); // reset the clock to track that
    }
    // Now whatever that was, it's still here after the debounceDelay
    if ((millis() - lastPadded) > debounceDelay) {
        // Well, if the pin is still LOW
        if (digitalRead(padPin) == LOW) {
            motor();
            speak("[:pitch 550] Love [:pitch 220] yoo.");
            sendServer(adore);
            if (padded) {
                padded = !padded;
            }
        }
    }
}

int speak(String word) {
    
    Serial.println(word);
    
    Serial1.print("S");
    Serial1.print("[:phoneme arpabet speak on]");
    Serial1.print("[:dv ap 450]");
    Serial1.print(word);
    Serial1.println();

    return 1;
}

// LED status
void connectStatus() {
    if ( client.connected() ) {
        // digitalWrite LED to ORANGE
        //digitalWrite(D0, HIGH);
    }
    if ( WiFi.ready() ) {
        // digitalWrite LED to CYAN
        digitalWrite(statusPin, HIGH);
    } 
    while ( WiFi.connecting() ) {
        // digitalWrite LED to GREEN
        digitalWrite(statusPin, HIGH);
        delay(500);
        digitalWrite(statusPin, LOW);
        delay(500);
    }
    if ( WiFi.listening() ) {
        // digitalWrite LED to BLUE
        if ( !WiFi.hasCredentials() ) {
            WiFi.setCredentials("MyWifi", "MyWifiPassword");
        }
    }
}

// Interrupt Service Routines
void isPadded() {
    padded = !padded;
}

void isPoked() {
    poked = !poked;
}

void isTilted() {
    tilted = !tilted;
}

void isNoisy() {
    noisy = !noisy;
}

HI @metaculus

I don’t know why this worked for you before, but the problem is that min and max are currently defined as macros on Spark and so they conflict with min and max methods in some C++ classes like array.

The work-around is simple–you need to undefine the min and max macros before the include for array:

#define RANDOM(maxRand) (rand() % maxRand)
#undef min
#undef max
#include <array>
...

I believe this is on the list to be fixed in an upcoming release.

2 Likes

Thank you @bko. I have no idea why but probably because I was using the code with another version of Spark.