Customization of an Arduino library on Github

Hello to everybody,

I'm working with an Arduino Wifi 1010 and an MkR IoT Carrier on a smart garden project. I wanted to do a change in the Arduino.h library, in particular here:

#define OUTPUT 0x1

I would like to change this OUTPUT variable to 0x0 due to a problem with an initialisation of a relay. However, Arduino.h is a standard library of Arduino and it is used by other libraries that I include in project (like Arduino_MKRIoTCarrier.h) , how can I change it? Should I download it in local, make a copy and do the modification? However, should I modify also Arduino_MKRIoTCarrier.h because I have to tell it that I want to Arduino_MKRIoTCarrier.h includes Arduino.h customised by me and not the standard one on github.

I'm not an expert on this, sorry for my stupid question.
Thanks in advance,
Lorenzo

That makes absolutely no sense since INPUT, OUTPUT and INPUT_PULLUP are fundamental constants in Arduino. You should find another way of doing what you want (I do not fully understand the problem).

Can you explain the problem? Can you post a sample piece of code that demonstrates the problem?

As already stated, altering fundamental constants makes no sense and will very likely lead to even bigger problems for you.

Do you mean this definition in Common.h?

typedef enum {
  INPUT           = 0x0,
  OUTPUT          = 0x1,
  INPUT_PULLUP    = 0x2,
  INPUT_PULLDOWN  = 0x3,
} PinMode;

That should not be used anywhere except when calling pinMode():
void pinMode( pin_size_t ulPin, PinMode ulMode )

You should be able to set those enumerated values to anything you like and when the core gets re-compiled it will use the new definitions. The code will behave exactly the same unless someone DOESN'T use the enum when calling pinMode().

Yes, of course. The idea of my code is to control remotely the waterpump by means the Arduino IoT Cloud. However I noticed that sometimes can happen (but I don't understand why) the Arduino board resets itself: so it turns off and on in few seconds. However, everytime it happens it performs the setup() function in my code and thus also the line (the full code is attached down):

Carrier.Begin();

Inside this function there is the initialisation of all the sensors and objects, including also the Relays. I attach here the class: Arduino_MKRIoTCarrier/Arduino_MKRIoTCarrier.cpp at master · arduino-libraries/Arduino_MKRIoTCarrier · GitHub. In particular you can see at lines 74 and 75 that there is:

Relay1.Begin();
Relay2.Begin();

and going in the library: Arduino_MKRIoTCarrier/Arduino_MKRIoTCarrier_Relay.cpp at master · arduino-libraries/Arduino_MKRIoTCarrier · GitHub
there is:

void MKRIoTCarrier_Relay::begin(){
    pinMode(_pin ,OUTPUT);
    close();
}

Ok. That's my problem. Every time the Arduino resets it self (for some obscure reason) the Relay pin is put on OUTPUT (= 0x1, I guess it means ON) and the waterpump gives water for that few second of reset time. And it's a problem for a smart garden, although are only few seconds the water pump gives water without my control.

So my idea was to change the value of that OUTPUT or the MKRIoTCarrier_Relay::begin() function, maybe with:

void MKRIoTCarrier_Relay::begin(){
    pinMode(_pin ,LOW);
    close();
}

Anyway, I attach here also my code:

#include <Arduino_MKRIoTCarrier.h>

#include "thingProperties.h"
MKRIoTCarrier carrier;
 
String waterPumpState;
String lightState;
int moistPin = A5;

int wateringTimeInSeconds=5000;
int t = 0;
int dry = 1023;
int wet = 0;

uint32_t lightsOn = carrier.leds.Color(82, 118, 115);
uint32_t lightsOff = carrier.leds.Color(0, 0, 0);

//_______
void setup() {
  // // Initialize serial and wait for port to open:
  Serial.begin(9600);
  //while (!Serial);

  // Defined in thingProperties.h
  initProperties();

  //Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
  
  //Wait to get cloud connection to init the carrier
  while (ArduinoCloud.connected() != 1) {
    ArduinoCloud.update();
    delay(500);
  }
 
  CARRIER_CASE = true;
  carrier.begin();
  carrier.display.setRotation(0);
  delay(500);
  
  carrier.Relay1.close();
  waterPumpState = "PUMP: OFF";
  updateScreen();
  
  delay(1500);
}

//_______
void loop() {

  ArduinoCloud.update();

  //Update touch buttons
  carrier.Buttons.update();
  //function to print out values
  if (carrier.Buttons.onTouchDown(TOUCH0)) {
    printInfo();
  }
  if (carrier.Buttons.onTouchDown(TOUCH1)) {
    printInfoRelays();
  }
  
  //read temperature and humidity
  temperature = carrier.Env.readTemperature();
  humidity = carrier.Env.readHumidity();
  //read raw moisture value
  int raw_moisture = analogRead(moistPin);
  //map raw moisture to a scale of 0 - 100
  moisture = map(raw_moisture, wet, dry, 100, 0);
  
  //read ambient light
  while (!carrier.Light.colorAvailable()) {
    delay(5);
  }
  int none;
  carrier.Light.readColor(none, none, none, light);
  
  if (waterpump == false){
    t = 0;
    carrier.Relay1.close();
  } 
  
  if (waterpump == true) {
    carrier.Relay1.open();
    if (t == 0){
      waterPumpState = "PUMP: ON";
      updateScreen();
    }
    t = t + 1000;
  }
  
  if (t >= wateringTimeInSeconds){
    waterpump = false;
    waterPumpState = "PUMP: OFF";
    updateScreen();
  }
  
  delay(1000);
}

//_______
void onArtificialLightChange() {
  if (light_state == true) {
    carrier.leds.fill(lightsOn, 0, 5);
    carrier.leds.show();
    lightState = "LIGHTS: ON";
  } else {
    carrier.leds.fill(lightsOff, 0, 5);
    carrier.leds.show();
    lightState = "LIGHTS: OFF";
  }
  updateScreen();
}


//Update displayed Info
void printInfo(){
  carrier.display.fillScreen(ST77XX_BLACK);
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.setTextSize(2);
 
  carrier.display.setCursor(40, 60);
  carrier.display.print("Water: ");
  carrier.display.print(moisture);
  carrier.display.println("%");
  
  carrier.display.setCursor(40, 80);
  carrier.display.print("T: ");
  carrier.display.print(temperature);
  carrier.display.println("C");
  
  carrier.display.setCursor(40, 100);
  carrier.display.print("Hum: ");
  carrier.display.print(humidity);
  carrier.display.println("%");
}

//_______
void printInfoRelays(){
  carrier.display.fillScreen(ST77XX_BLACK);
  carrier.display.setTextColor(ST77XX_WHITE);
  
  carrier.display.setTextSize(3);
  carrier.display.setCursor(40, 50);
  carrier.display.print(waterPumpState);
  carrier.display.setCursor(40, 90);
  carrier.display.print(lightState);
}

Thanks again and sorry for my inexperience
Lorenzo

Thanks Danois90. I explained in depth my problem in another message. You can find there all the details. I hope that the problem is clearer now

Thanks Johnwasser for your answer. I explained in depth my problem in another message. You can find there all the details. I hope that the problem is clearer now

"OUTPUT" has nothing to do with the state of the pins, it is the direction. A pin has to be OUTPUT in order to control your relay by setting the pin to either "HIGH" or "LOW".

When the board resets, the pins return to their default state during boot. Some pins are "HIGH" by default, others are "LOW". Your problem may be solved by simply finding a pin which has "LOW" as its default state.

You should also find out what the cause of the occasional reset is. This may be caused by a WatchDog (hanging code) or by a hardware issue. If it is a hardware issue, your device may break at some point, so worth to investigate.

With MkR IoT Carrier, the two relays switch on when signal is LOW.

I don't know very well Arduino Wifi 1010 board, but I suppose that, as with other boards, when you define a GPIO pin as OUTPUT, as default value it will setted to LOW, so the relay switch on a little time until you call the method close().

This a well known behaviour and with some board to avoid this is enought enable the pull-up resistor on that gpio BEFORE setting as OUTPUT.

The method that opens the relay sets the pin to HIGH? Or am I missing something?

The schematic for the carrier board shows that there are pull-down resistors attached to the gates of the MOSFET drivers of both relays.


This should prevent the behaviour you describe, so I wonder if you are using the relays incorrectly? For example attaching the pumps to the Normally Closed (NC) contact instead of the Normally Open (NO) contact? See page 12 of the data sheet.

Certainly your proposal to change the library code to fix this a) won't work; b) would have unwanted side effects; c) is entirely the wrong approach!

1 Like

Yes @Danois90 you are right, I've checked better the schematic.
What i've wrote before it's wrong... relays on board is ON when signal is HIGH.

The function MKRIoTCarrier_Relay::close() sets the relay output pin LOW. The function MKRIoTCarrier_Relay::open() sets the relay output pin HIGH.

MKRIoTCarrier_Relay::begin() calls close() so it sets the output pin LOW and turns the water pump OFF.

Whatever is causing the water pump to turn ON (carrier.Relay1.open()), it is NOT the library.

Also, shortly after you call carrier.begin(); in setup() you also call carrier.Relay1.close(); which would turn off the water pump EVEN IF carrier.begin() had turned it on.

There must be a mistake elsewhere in your sketch that is turning the water pump on when you don't want it to be on. Check your program logic.

If the library is locally available, he could just comment out line 28 in Arduino_MKRIoTCarrier_Relay.cpp. That could prevent the relay from turning off when "begin()" is called - but I'm not sure it is going to work since the pins have a default state during boot.

Thanks a lot for your suggestions. I attach here two pictures about my connections. I used the NO contact in order that the relay is closed unless I enable the relay. Is it correct?


Thanks again,
Lorenzo

Thanks for you answer. I don't really know how to find the problem. Do you think could be a problem related to the power supply? Since I cannot leave the arduino connected for many days to a Computer, I tried to power the Arduino with electric socket by means this:


You have connected the relay to "NO" (Normally Open), this will have the relay being open as default. If you want the relay to be closed as default, it should be connected to "NC" (Normally Closed).

EDIT: Your 1A / 5 Watt power plug is fine, I do not think the issue is related to power. Your connections / wiring on the other hand...... :roll_eyes: :joy:

You are correct to use the NO contacts. But this means the relay will be open until it is energised. "Open" means the relay contacts are open and no current can flow to power the pump. When you energise the relay, the contacts will close and current will flow to power the pump.

I tried also to connect the waterpump to "NC" and, actually, I can solve the resetting problem. However, after that few seconds of reset the pump stays ON forever until I give the command to close the waterpump. So, I thought that what I need is the NO state.

What do you mean that my connections/wiring are not fine? If you mean in terms of esthetics I agree with you, but it was a fast example to show you. If you mean that I did some mistakes, please tell me.

Thanks

It looks like the wires are connected using masking tape, that's absolutely not ideal.. As already mentioned earlier, I think your resets are related to a watchdog reset. Looking at your code, the only thing I can spot that would cause this is the call to "ArduinoCloud.update()" in "loop()". If you get rid of the resets, the problem with the relay coming on and off is no longer an issue.