Arduino Compatibility is Awesome!!!

benrbenr Seattle
edited February 26 in Mongoose OS

I wanted to extend a big thank you to rojer for the start of Adruino compatibility! It's awesome.

I took some simple Arduino code I prototyped on an Adruino Micro working on my ESP32. I wanted to share how I did it.

Here is the original Arduino code:

const byte RED_LED = 16;
const byte GRN_LED = 17;
const byte SENSOR = 5;

void setup() {
  Serial.begin(115200);

  pinMode(RED_LED, OUTPUT);
  pinMode(GRN_LED, OUTPUT);
  pinMode(SENSOR, INPUT_PULLUP);
}

void loop() {

  if (digitalRead(SENSOR) == HIGH){
    Serial.println("Door is open.");
    openSignal(true);
  } else {
    Serial.println("Door is closed.");
    openSignal(false);
  }
  delay(1000);
}

void openSignal(bool state){
  if (state){
    digitalWrite(RED_LED, LOW);
    digitalWrite(GRN_LED, HIGH);
  } else {
    digitalWrite(RED_LED, HIGH);
    digitalWrite(GRN_LED, LOW);
  }
}

I put that code in src/main.cpp, then add a C++ class to implement the Serial object, provide a function declaration to quiet compiler warnings, and include Arduino.h. So, I slap this on top of the code above:

#include <Arduino.h>

// Function declarations for custom functions:
void openSignal(bool state);

// Implement Serial object for Arduino compatability 
class SerialConsole {

 public:
   void begin(void* x){
      printf("Serial Initialized.\n");
   }
   void println(void* input){
      printf("%s\n", input);
   }

};

// Instantiate the Serial Object
SerialConsole Serial;

// Arduino code goes below:

Build and flash it to the ESP32 and it works perfectly!

The Arduino support is still early and Analog GPIO isn't supported yet, but enough is there to allow anyone to fill in the missing pieces like I did.

If you want to play with it, just make sure your project has " MGOS_ENABLE_ARDUINO_API: 1" as a build flag in mos.yml.

Thanks rojer!!!!!

Comments

  • benrbenr Seattle

    A word of warning for anyone playing with Arduino. In my environment the ESP32 watchdog timer is set to 30 seconds and I can't change it. I even added mgos_wdt_disable(); to my setup() function, and it still doesn't disable the watchdog... therefore, both the "c_hello_arduino" example (https://github.com/cesanta/mongoose-os/tree/master/fw/examples/c_hello_arduino) and my example above will fail to reset the watchdog and the system will dump core after 30 seconds.

  • benrbenr Seattle
    edited February 26

    I figured it out, ignore the post above.

    Calling mgos_wdt_disable(); from my setup() function didn't fix the problem. However, feeding the timer (ie: resetting the watchdog timer) in the loop() does work just fine.

    To do this, include the fw/src/mgos_hal.h header and then call mgos_wdt_feed(); in the loop function. Here is a "fixed" source for c_hello_arduino as an example:

    #include <Arduino.h>
    #include "fw/src/mgos_hal.h"
    
    void setup(void) {
    
      printf("Hello, Arduino world!\r\n");
      pinMode(2, OUTPUT);
    }
    
    void loop() {
      static boolean value = 0;
      digitalWrite(2, value);
      printf("%s\r\n", (value == 0 ? "Tick" : "Tock"));
    
      mgos_wdt_feed();
      delay(500);
      value = (value ? 0 : 1);
    }
    
  • SergeySergey Dublin, Ireland

    Very cool, thank you.
    I wonder does it make sense to do a drop-in support.
    Like, allow dropping an .ino file with appropriate drivers into the src/ directory.

  • benrbenr Seattle

    @Sergey said:
    Very cool, thank you.
    I wonder does it make sense to do a drop-in support.
    Like, allow dropping an .ino file with appropriate drivers into the src/ directory.

    Yes, absolutely.

    One idea might be to allow the .ino file to be in the project root. If that were the case, you could check out an existing Arduno project (stored in Project_Name/Project_Name.ino), then "mos init --arduino" right over the top of it to add the MGOS structure. In this way you could have an easy onboarding flow: Go to your Arduino project directory, mos init, mos build --arch esp32 --local, mos flash, done!

  • Trying to play with arduino and stuck right away.

    Started with:

    adotka@homer:~/MOS$ mkdir mos_arduino
    adotka@homer:~/MOS$ cd mos_arduino/
    adotka@homer:~/MOS/mos_arduino$ mos init --arch esp8266
    Connecting to http://mongoose.cloud, user  ...
    Downloading project skeleton...
    Unpacking...
    Setting arch "esp8266"...
    adotka@homer:~/MOS/mos_arduino$ mos build
    Connecting to http://mongoose.cloud, user test
    Uploading sources (2778 bytes)
    Success, built mos_arduino/esp8266 version 1.0 (20170312-083349/???).
    Firmware saved to build/fw.zip

    So far so good..
    Then edited mos.yml as follows:

    version: "1.0"
    arch: esp8266
    mongoose_os_version: master
    sources:
    src
    filesystem:
    fs
    extra_files: []
    skeleton_version: 2016-11-24
    ffi_symbols: []
    build_vars:
      APP_CONF_SCHEMA: src/conf_schema.yaml
      MGOS_ENABLE_ARDUINO_API: 1

    And then mos build fails:

    adotka@homer:~/MOS/mos_arduino$ mos build
    Connecting to http://mongoose.cloud, user test
    Uploading sources (2804 bytes)
    The flag --repo is not given, going to use mongoose-os repository
    Building...
    Make arguments: -j -f mongoose-os/fw/platforms/esp8266/Makefile FS_STAGING_DIR=build/fs PLATFORM=esp8266 GEN_DIR=build/gen APP=mos_arduino MGOS_PATH=mongoose-os MGOS_ENABLE_ARDUINO_API=1 FW_DIR=build/fw APP_FS_PATH=fs APP_VERSION=1.0 APP_MODULES=src FFI_SYMBOLS= BUILD_DIR=build/objs APP_CONF_SCHEMA=src/conf_schema.yaml

    -------------SKIP--------------

    LD    /app/build/objs/mos_arduino.elf
    /app/build/objs/mongoose-os.a(mgos_arduino.cpp.o):(.text.loop_cb+0x4): undefined reference to 'loop'
    /app/build/objs/mongoose-os.a(mgos_arduino.cpp.o): In function 'loop_cb':
    /mongoose-os/fw/src/Arduino/mgos_arduino.cpp:51: undefined reference to 'loop'
    /mongoose-os/fw/src/Arduino/mgos_arduino.cpp:51: undefined reference to 'setup'
    /app/build/objs/mongoose-os.a(mgos_arduino.cpp.o):(.text.mgos_arduino_init+0xa): undefined reference to 'setup'
    collect2: error: ld returned 1 exit status
    /mongoose-os/fw/platforms/esp8266/Makefile.build:361: recipe for target '/app/build/objs/mos_arduino.elf' failed
    make: *** [/app/build/objs/mos_arduino.elf] Error 1
    mongoose-os/fw/docker_common.mk:90: recipe for target 'all' failed
    make: *** [all] Error 2
    Error: exit status 2
    Error: build failed

    Am I missing something?

  • edited March 12

    Amm... I have missed setup() and loop() in main.c :) Sorted.

  • SergeySergey Dublin, Ireland

    @adotka does it work for you as expected now?

Sign In or Register to comment.