Arduino Explore IoT Kit: Activity 7

Hello. In Activity 7 of the Explore IoT Kit there is a switch case statement in loop() that iterates through the various screens used in this activity. Switch details are given under the heading "Screens workflow" under Activity 7: "Cloud vs Carrier Game". In my case, when I execute the switch as given by Arduino, loop() executes a 1st iteration (i.e., goes through each of the screens normally) but on the second pass through loop() it resets the MKR WiFi 1010 board, and the sketch restarts by executing setup() again. This behaviour is repeated permanently. Any suggestions on what's happening?? Thank in advance. AlexA

Please post the full sketch here, using < CODE/ > tags when you do

These are the main sketchs. The first has setup() and loop(). The 2nd is the additional header file Screens.h used in Activity 7. Sorry for the verbose of my own comments...

// BSEC Software Library - Version: 1.6.1480
// #include <bsec.h>

/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled"
  https://create.arduino.cc/cloud/things/e6fb2fe5-ca69-4248-b246-52eaedfc77c9 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  String results;
  int boardBeans;
  int boardGuess;
  int cloudBeans;
  int cloudGuess;
  bool boardBeansReady;
  bool boardGuessReady;
  bool cloudBeansConfirm;
  bool cloudGuessConfirm;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h" // Header for WiFi connection functionalities & cloud connection 
// management; the only information required from user are credentials necessary to establish a 
// connection with a WiFi network (SSID and PASSWORD). Autogenerated to connect to cloud
// ArduinoIoTCloud library, it's central element of firmware enabling certain Arduino boards to connect 
// to Arduino IoT Cloud. Firmware is software that provides basic machine instructions that allow 
// hardware to function and communicate with other software running on device. 
// Provides low-level control for device's hardware.
//
// NOTE: library for carrier and its object not needed here (inclusion/init done in included Screen.h)
// #include <Arduino_MKRIoTCarrier.h> // Carrier's library to access carrier's functionality
// Sensors: temperature & humidity, barometric pressure, accelerometer & gyroscope, ambient light, 
// gesture and proximity, capacitive buttons. Actuator: Buzzer, RGB, display, relays, relay status LEDs
// MKRIoTCarrier carrier; // Instance of a carrier used to access functionality
#include "Screens.h"

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  initProperties(); // Properties defined in "thingProperties.h". Autogenerated to connect to cloud
  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection); // Autogenerated to connect to cloud
  // carrier.Buttons.begin(); //Init the calibration and set up for touchable pads (NO NEED, already 
  // done in the MKRIoTCarrier class’ begin())
  //NOTE: I had following two lines AFTER while( ArduinoCloud.connected() != 1) and did not work!!
  // Makes sense: need to create a carrier object before connecting to the cloud (???)
  CARRIER_CASE = true; // Carrier is mounted on the case 
  carrier.begin(); //Initialize the IoTSK carrier and output any errors in the serial monitor
  /* The following function allows you to obtain more information related to the state of network 
     and IoT Cloud connection and errors, the higher number the more granular information you’ll get.
     The default is argument is 0 (only errors). Maximum is 4 */
  setDebugMessageLevel(4);   //Get Cloud Info/errors , 0 (only errors) up to 4
  ArduinoCloud.printDebugInfo(); //Allows for more information related to the state of the network and 
  // IoT Cloud Connection and errors. The higher the number set for setDebugMessageLevel the more 
  // information is displayed. The maximum is however 4 and the minimum is zero.

// As part of setup(), wait to get cloud connection to initialize the carrier
  while( ArduinoCloud.connected() != 1) { // If no connection, execution stuck in this loop
    ArduinoCloud.update();
    carrier.display.setTextSize(2);
    carrier.display.setCursor(10, 40);
    carrier.display.println("Wait for connection");
    carrier.display.setCursor(10, 60);
    carrier.display.println("to Arduino cloud..." );
    delay(1000);
  }
//carrier.display.setRotation(0); // Sets angle of screen. 0 is starting position: no rotation.
// The screen can only be rotated 90, 180 or 270 degrees by replacing the 0 with 1, 2 or 3.
// If here, connection to Cloud has been established (hopefully!!)
  carrier.display.setCursor(10, 80);
  carrier.display.setTextColor(ST77XX_YELLOW); // Text color
  carrier.display.println("In Arduino cloud!!");
  carrier.display.setCursor(10, 100);
  carrier.display.println("Activity 7 starts");
  delay(2000); // Wait 2 seconds before going into loo()

} // End of setup()

void loop(){
  switch (screen){
    screen = 0; // Is this necessary??
    case 0:
        mainScreen();
        delay(1500);
        screen = 1; 
    break;
    case 1:
        guessScreen();
        delay(1500);
        screen = 2; 
    break;
    case 2:
        beansScreen();
        delay(1500);
        screen = 3; 
    break;
    case 3:
        resultsScreen();
        delay(1500);
        screen = 4; 
    break;
    case 4:
        p1_winnerScreen();
        delay(1500);
        screen = 5; 
    break;
    case 5:
        p2_winnerScreen();
        delay(1500);
        screen = 6; 
    break;
    case 6:
        tieScreen();
        delay(1500);
        screen = 0; 
    break;
  }
}// End of loop()

/*
  Since CloudBeans is READ_WRITE variable, onCloudBeansChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onCloudBeansChange()  {
  // Add your code here to act upon CloudBeans change
}

/*
  Since CloudBeansConfirm is READ_WRITE variable, onCloudBeansConfirmChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onCloudBeansConfirmChange()  {
  // Add your code here to act upon CloudBeansConfirm change
}

/*
  Since CloudGuess is READ_WRITE variable, onCloudGuessChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onCloudGuessChange()  {
  // Add your code here to act upon CloudGuess change
}

/*
  Since CloudGuessConfirm is READ_WRITE variable, onCloudGuessConfirmChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onCloudGuessConfirmChange()  {
  // Add your code here to act upon CloudGuessConfirm change
}

// We create a separate tab that will "house" the header file Screens.h (a header file is an extension of our main 
// program, often used to store larger amounts of code, so that our main program is easier to navigate). Screens.h
// is used to initialize the carrier object that will allow us to use the different functions to control the 
// MKR loT Carrier. We will also create other functions to program the behavior of the different screens for the game.
#include <Arduino_MKRIoTCarrier.h>
MKRIoTCarrier carrier;
// Now we initialize the variables that we will use later on while programming the game stages.
bool screen_flag = true;
int screen = 0;
int num = 0;
int boardProv = 0;
int randomX;
int randomY;
bool boardGuess_confirm = false;

// Function for initial screen of the game, prints message with name of game and smaller text indicating how to start.
void mainScreen(void)
{
  carrier.display.fillScreen(ST77XX_BLACK);
  carrier.display.setTextSize(4);
  carrier.display.setTextColor(ST77XX_RED);
  carrier.display.setCursor(50, 40);
  carrier.display.print("SPOOF");
  carrier.display.setTextSize(3);
  carrier.display.setCursor(5, 95);
  carrier.display.print("A Barfly Game");
  carrier.display.setTextSize(2);
  carrier.display.setCursor(15, 200);
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.print("Press 02 to start");
}

// Function to program screen to do the following:
// 1) Player playing on the carrier (P1) will guess the total number of beans. 
// 2) Screen will give feedback of the game state of the player playing on the cloud (P2), as well as their guess number. 
// 3) Top of carrier screen has two: (P2_G) and (P2_N). 
//    --P2_G mark will let the carrier player know the total amount of beans that the player on the cloud guessed. 
//    --P2_N mark will let the carrier player know the guess state of the player on the cloud, if guess state is confirmed a green circle will appear. 
void guessScreen(void)
{
  carrier.display.fillScreen(ST77XX_BLACK);
  carrier.display.setTextSize(3);
  
  carrier.display.setTextColor(ST77XX_BLUE);
  carrier.display.setCursor(5, 8);
  carrier.display.print("P2_G");
  carrier.display.drawCircle(95, 17, 15, ST77XX_GREEN);
  
  carrier.display.setCursor(125, 8);
  carrier.display.print("P2_N");
  carrier.display.drawCircle(215, 17, 15, ST77XX_GREEN);
  
  carrier.display.setTextSize(2);
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.setCursor(20, 55);
  carrier.display.print("P1 guessed number");
  
  carrier.display.setTextSize(3);
  carrier.display.setCursor(60, 90);
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.print("Confirm");
  
  carrier.display.setTextSize(5);
  carrier.display.setCursor(20, 200);
  carrier.display.print("+");
  carrier.display.setCursor(200, 200);
  carrier.display.print("-");
  
  carrier.display.setCursor(110, 150);
  carrier.display.setTextColor(ST77XX_GREEN);
  carrier.display.print(boardGuess);
}

// Function to program the screen on which the player using the carrier (P1) will choose the number of beans to play with. 
// Top part of this screen works exactly the same as in guessScreen: provide feedback on how the player playing on the cloud is doing.
void beansScreen(void)
{
  carrier.display.fillRect(0, 34, 240, 205, ST77XX_BLACK);
  carrier.display.setTextSize(2);
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.setCursor(35, 55);
  carrier.display.print("P1 beans number");
  
  carrier.display.setTextSize(3);
  carrier.display.setCursor(60, 90);
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.print("Confirm");
  
  carrier.display.setTextSize(5);
  carrier.display.setCursor(20, 200);
  carrier.display.print("+");
  carrier.display.setCursor(200, 200);
  carrier.display.print("-");
  carrier.display.setCursor(110, 150);
  
  carrier.display.setTextColor(ST77XX_GREEN);
  carrier.display.print(boardBeans);
}

// Function to show in the display the numbers that both players have chosen to play with.
void resultsScreen(void)
{
  carrier.display.fillScreen(ST77XX_BLACK);
  carrier.display.setTextColor(ST77XX_BLUE);
  carrier.display.setTextSize(5);
  carrier.display.setCursor(20, 0);
  carrier.display.print("RESULTS");
  
  carrier.display.setTextColor(ST77XX_GREEN);
  carrier.display.setCursor(100, 50);
  carrier.display.print("P1"); // Carrier player
  carrier.display.setCursor(180, 50);
  carrier.display.print("P2"); // Cloud player
  
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.setTextSize(3);
  carrier.display.setCursor(0, 180);
  carrier.display.print("Beans");
  carrier.display.setCursor(0, 115);
  carrier.display.print("Guess");
  
  carrier.display.setTextSize(5);
  carrier.display.setCursor(110, 110);
  carrier.display.print(boardGuess);
  carrier.display.setCursor(180, 110);
  carrier.display.print(cloudGuess);
  
  carrier.display.setCursor(110, 170);
  carrier.display.print(boardBeans);
  carrier.display.setCursor(180, 170);
  carrier.display.print(cloudBeans);

}

// Function to provide feedback for the game winner, here the winner is the player playing on the CARRIER.
void p1_winnerScreen(void) {
  carrier.display.fillScreen(ST77XX_WHITE);

  for (int i=0; i < 8; i++) { // Used to make 8 circles at random positions on the carrier's display
    randomX = random(0, 240); // Random x position of pixel
    randomY = random(0, 240); // Random y position of pixel
    carrier.display.fillCircle(randomX, randomY, 20, ST77XX_GREEN); // Draw circle at x,y position
  }
 
  carrier.display.setTextColor(ST77XX_ORANGE);
  carrier.display.setTextSize(5);
  carrier.display.setCursor(30, 60);
  carrier.display.print("WINNER");
  carrier.display.setCursor(100, 110);
  carrier.display.print("P1");
}
 
// Function to provide feedback for the game winner, here the winner is the player playing on the CLOUD.
void p2_winnerScreen(void) {
  carrier.display.fillScreen(ST77XX_BLACK);
 
  for (int i=0; i < 8; i++) {// Used to make 8 circles at random positions on the carrier's display
    randomX = random(0, 240);
    randomY = random(0, 240);
    carrier.display.fillCircle(randomX, randomY, 20, ST77XX_RED);
  }
 
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.setTextSize(5);
  carrier.display.setCursor(30, 60);
  carrier.display.print("WINNER");
  carrier.display.setCursor(100, 110);
  carrier.display.print("P2");
}
 
 // Function to provide feedback that there is a tie, NO winner of the game.
void tieScreen(void) 
{
  carrier.display.fillScreen(ST77XX_ORANGE);
 
  for (int i=0; i < 4; i++) {
    randomX = random(0, 240);
    randomY = random(0, 240);
    carrier.display.fillCircle(randomX, randomY, 20, ST77XX_RED);
    carrier.display.fillCircle(randomY, randomX, 20, ST77XX_GREEN);
  }
 
  carrier.display.setTextColor(ST77XX_BLACK);
  carrier.display.setTextSize(5);
  carrier.display.setCursor(90, 100);
  carrier.display.print("TIE");
}

// Function to update the information on the screen
void numberUpdate(int number)
{
  carrier.display.setTextSize(5);
  carrier.display.fillRect(60, 115, 130, 100, ST77XX_BLACK);
  carrier.display.setCursor(110, 150);
  carrier.display.setTextColor(ST77XX_GREEN);
  carrier.display.print(number);
}
 
// Function to reset all the values to start a new game.
void resetValues(void)
{
  screen = 0;
  cloudGuess = 0;
  cloudBeans = 0;
  boardGuess = 0;
  boardBeans = 0;
  boardProv = 0;
  cloudBeansConfirm = false;
  cloudGuessConfirm = false;
  boardGuess_confirm = false;
  boardBeansReady = false;
  boardGuessReady = false;
  num = 0;
}

Just adding some data. I have changed the delay(1500) to delay(500) and the reset of my MKR WiFi 1010 (or the MKR IoT Carrier??) happens ALWAYS after 8000 millisecs. In other words, using delay(500) in loop() the reset happens in the 3rd iteration of loop(0 as opposed to the 1st when using delay(1500). Is the Arduino IoT Cloud doing the reset or it's the board/carrier??

In the section of Screens workflow, it is meant to iterate through the 7 different screens to demonstrate the different screens. However, if you would like it to loop continuously you would then need to add the following ArduinoCloud.update() to your loop() function:

void loop() {
    ArduinoCloud.update();
    switch (screen){
     screen = 0;
    }
}
1 Like

Right on, thanks a million!! You saved my day.
Your answer also made me wonder about a couple of things:
--I'm only communicating to the MKR Carrier through USB cable, why do I need to update the cloud with ArduinoCloud.update()??
--Without ArduinoCloud.update(), what is getting reset, the cloud, the carrier or the board, and why??
Thanks a lot again!!

1 Like

The following should answer your question > GitHub - arduino-libraries/ArduinoIoTCloud

Thanks!

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.