4

I'm trying to use an existing Arduino library on the Raspberry Pi Pico. The library is here:

https://github.com/j-bellavance/EdgeDebounce/tree/master

It's based on some interesting insight at Jack Ganssel's blog: http://www.ganssle.com/debouncing.htm

The library works great on an ATMega 328, but I got two errors when changing to the Raspberry Pi Pico.

The first one was resolved by editing the last line of EdgeDebounce.h like this:

//#endif;  // Arduino ATMega version
#endif   // Pico version, also works on ATMega

The second is a bit more complex. Here's the relevant section of code, these are lines 78 - 102 in EdgeDebounce.cpp :

  byte EdgeDebounce::debounce(byte pin) {
  unsigned long pinStatus;
  do {
    pinStatus = 0xffffffff;
    for (byte i = 1; i <= MYsensitivity; i++) pinStatus = (pinStatus << 1) | digitalRead(pin);
  } while ((pinStatus != debounceDontCare) && (pinStatus != 0xffffffff));
  return byte(pinStatus & 0x00000001);  
}//debounce------------------------------------------------------------------------------------------------

//updateStatus===================================================================
//After releasing EdgeDebounceLite, I realized that EdgeDebounce could do more
//With this small piece of code, EdgeDebounce can return if a switch is
//  .isclosed();  //Conducting current
//  .isopen();    //Not conducting current
//  .rose();      //Just went from open to closed
//  .fell();      //just went from closed to open
//-------------------------------------------------------------------------------
void EdgeDebounce::update() {
  byte newStatus = debounce();
  if (MYmode == PULLUP) newStatus = !newStatus;
  if (MYstatus == OPEN && newStatus == CLOSED) MYrose = true;
  else                                         MYrose = false; 
  if (MYstatus == CLOSED && newStatus == OPEN) MYfell = true;
  else                                         MYfell = false;
  MYstatus = newStatus;
}//update-------------------------------------------------------------------------

When I try to compile, I get this error:

c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp: In member function 'void EdgeDebounce::update()':
c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp:102:14: error: invalid conversion from 'byte' {aka 'unsigned char'} to 'pinStatus' [-fpermissive]
  102 |   MYstatus = newStatus;
      |              ^~~~~~~~~
      |              |
      |              byte {aka unsigned char}

exit status 1

Compilation error: exit status 1

So I see that the byte of "newStatus" doesn't convert to "pinStatus" which is an unsigned long. I've done a bunch of Google searches but can't quite figure out what the fix is.

1
  • Where is pinStatus declared? Not inside EdgeDebounce::debounce - that's a local declaration.
    – Nick Gammon
    Commented Jul 13, 2023 at 7:27

2 Answers 2

4

In C and in much pre-standard C++ nothing stops you just assigning an integer value to a variable of enumeration type. In standard C++ (from 1998 onward) that requires an explicit type conversion (a "cast").

The AVR Arduino core supplies the -fpermissive option to the compiler which among other things allows the implicit conversion they're doing despite not being standards compliant C++. Whatever you're using (odds are this or this) for RPI Pico Arduino core does not provide the -fpermissive option. A lot of Arduino cores don't and probably shouldn't.

You could modify the RPI Pico core's platform.txt to give the -fpermissive option to g++, but it is probably better to make the code compliant.

Minimal change

There are probably dozens of ways to do this, but a combination of mimimal and pleasing to C++ nerds probably looks like:

MYstatus = static_cast<pinStatus>(newStatus);

Alternative Casts

MYstatus = static_cast<decltype(MYstatus)>(newStatus); // fancier
MYstatus = (pinStatus)newStatus;  // traditional cast
MYstatus = pinStatus(newStatus);  // function-style cast
MYstatus = (decltype(MYstatus))newStatus;  // uhhh
MYstatus = (decltype(MYstatus))(newStatus);  // sure... why not?

The static_cast declares in intent in a way that other types of cast don't. decltype would make that line survive changes to the type of MYstatus better, but decltype is not as widely understood.

Alternately not type-converting at all

You can also observe that return byte(pinStatus & 0x00000001); is the only point of return from byte EdgeDebounce::debounce(byte pin). So you know this function returns either 0 (false) or 1 (truthy). That's just what's going to happen with applying & 1.

They've defined the enumeration type:

enum pinStatus {OPEN, CLOSED};

The rules of C and C++ (even pre-standard C++) will assign these constants numeric values 0 and 1, where they weren't explicitly given values and were listed in that order.

So, you could replace MYstatus = newStatus; with:

{
  if (newStatus) {
      MYstatus = CLOSED;
  } else {
      MYstatus = OPEN;
  }
}

Or use the ternary operator if you want don't mind people trying to argue with you:

MYstatus = newStatus ? CLOSED : OPEN;
2
  • It's apparently also possible to use braces for the function-style cast without a narrowing conversion diagnostic, which I didn't expect for this case. But, I'm not going to edit it again just to mention that
    – timemage
    Commented Jul 14, 2023 at 16:32
  • Thank you for taking the time to write such an in-depth answer! - I am using the Earle Philhower RP2040 core. - I read (and re-read) your comments until I understood them all. - I have tested all your suggested fixes above, and they all work. I don't mind the ternary operator, but I will go with your first suggested change. Thanks again.
    – Jeff Haas
    Commented Jul 14, 2023 at 23:20
0

pinStatus is an enum:

enum pinStatus {OPEN, CLOSED};

The pinStatus you posted is a local variable, nothing to do with pinStatus in the EdgeDebounce.h file.

The error is pointing out that you can't assign an unsigned char to an enum which can only hold OPEN and CLOSED. The unsigned char might hold various other values.

Whoever coded that has made some confusing code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.