I'm pretty new to Arduino development. I tried a couple of the sample programs in the Nesso 1 user manual. They've all worked pretty well.
But when I tried to combine using the M5GFX library and using the buttons, I never get button presses registered. I suspect that KEY1 and KEY2 are redefined somewhere in the graphics library. There are no compile errors. The code is literally just the combination of the hello world and user buttons programs.
I tried to define my own buttons as follows but this didn't work either:
ExpanderPin Key_1(0);
ExpanderPin Key_2(1);
This is the code. As I mentioned, it's a combination of the hello world and button programs. If I take out the graphics, I do get the serial output showing which button was pressed.
#include <M5GFX.h>
M5GFX display; // Create a display instance
void setup() {
pinMode(KEY1, INPUT_PULLUP);
pinMode(KEY2, INPUT_PULLUP);
Serial.begin(115200);
delay(1000);
display.begin();
display.setRotation(1); // Set to landscape mode
// Set text properties
display.setTextDatum(MC_DATUM); // Middle-Center datum for text alignment
display.setTextColor(TFT_WHITE, TFT_BLACK); // White text, black background
display.setTextSize(2);
// Clear the screen and draw the string
display.fillScreen(TFT_BLACK);
display.drawString("Hello, Nesso N1!", display.width() / 2, display.height() / 2);
}
void loop() {
if (digitalRead(KEY1) == LOW) {
Serial.println("Button 1 pressed!");
delay(200); // Simple debounce
}
if (digitalRead(KEY2) == LOW) {
Serial.println("Button 2 pressed!");
delay(200); // Simple debounce
}
}
There is something fundamental that I don't understand about how this works. I have the buttons working with my Matter and Display sketch that I'm trying to write. But now the built-in LED is not working! This is SOOO frustrating.
When I try the sample sketches. they work as advertised. But when I try to expand the code, things that worked previously, just simply stop working.
This is how I the LED works in the Nesso Matter example:
The following code gets called when the Matter device is turned on or off:
bool setLightOnOff(bool state) {
Serial.printf("Received Matter command: Light %s\r\n", state ? "ON" : "OFF");
// Control the built-in LED (inverted logic: LOW is ON)
digitalWrite(LED_BUILTIN, state ? LOW : HIGH);
return true;
}
I see the serial message being printed. But the LED does not turn off in my M5Unified sample.
Doe M5Unified handle digital outputs? How can I call digitalWrite and pinMode without including header files. What files are automatically included in my sketch? Why would something work and the EXACT SAME CODE stops working when I add something completely different? There is obviously some undocumented interaction between the libraries. I'm still guessing that including one thing #defines something else out of existence...
@b707 is right, you forgot to define KEY1 and KEY2, I wonder how the sketch even compiled. Not only that but @rogerguess provided a link to a sketch that showed the proper use of M5Unified:
// * - All buttons are on I2C expander (NOT direct GPIO!)
...
...
// Check Button A (KEY1)
if (M5.BtnA.wasPressed()) {
// Do here whatever has to be done when Button A (aka KEY1) is pressed
}
The point here is: All buttons are on I2C expander (NOT direct GPIO!) so you can't use pinMode(); or digitalRead(); or digitalWrite(); for these buttons!
There is a built in function helper for digitalWrite and digitalRead and pinMode, which support passing an ExpanderPin object instead of the pin number.
They need to be used with the #DEFINE pin names from the board variants pins header file:
I found I needed to add support for the ExpanderPin argument type to some 3rd party libraries to get that working seamlessly, e.g. like here where I've added new constructors:
In theory you might find just calling digitalWrite(LED_BUILTIN, LOW) to be enough.
Explain to me how the code below compiles and works. Maybe that will point me in the direction of how to solve my own issues.
That is ALL that is in the sketch. It is an exact copy of the sample code from https://docs.arduino.cc/tutorials/nesso-n1/user-manual/. There are no includes. Somehow, the system knows where KEY1 and KEY2 are defined. This code works. I get the messages printed in the serial console.
All arduino sketches get translated into a .cpp file before compiling. Basically the same content with #include Arduino.h at the top.
That include brings in the pins_arduino.h for your specific board, and that therefore makes the board specific defines (like LED_BUILTIN and KEY1) available anywhere in your program.
Each call to the function pinMode/digitalWrite/digitalRead first checks the argument types supplied, and looks for a matching function signature (in this case first argument is ExpandedPin class instance for KEY1 and second argument would be the value as int).
Normally there are only digitalRead/Write functions with int arguments, but with this board the Arduino team have added some extra helpers (function overloads) to support the same function name but with ExpandedPin arguments instead of just the pin number (uint8_t).
Yes I saw the comment and no, it is not relevant. The Nesso N1 has the logic reversed, so low / 0 to turn on. I also replaced all the defines with literals for the writes but that did not seem to work either.
If the state was reversed, then the light would still have turned on and off as I tested. But it does not change at all, even though the serial message shows that function is called with the correct value.
I suspect that maybe the ExpanderPin is being clobbered so it's calling the wrong digitalWrite function based on @tyeth's excellent information above.
Thanks a lot for the detailed reply! Looking in the headers I was able to get the code to work. I think the M5Unified code is clobbering something. But I was able to see in the M5 library code how to write to the outputs.
I replaced the digitalWrite with the following:
//digitalWrite(LED_BUILTIN, state ? 0 : 1);
M5.getIOExpander(1).digitalWrite(7, state ? 0 : 1);
It appears that the IO pins default to output and some of the pins are set to input in the M5 startup code. I was happy to see that the code does support the Nesso board.