HelTecAutomation / CubeCell-Arduino

Heltec CubeCell Series (based on ASR6501, ASR6502 chip) Arduino support.
247 stars 138 forks source link

Missing pinMode INPUT_PULLUP #23

Closed joergkeller closed 4 years ago

joergkeller commented 4 years ago

Using the DHT library (by Adafruit, version 1.3.8, https://github.com/adafruit/DHT-sensor-library) created a compile error because INPUT_PULLUP is not defined in Arduino.h or ASR_Arduino.h respective. I've modified DHT to use

    pinMode(_pin, INPUT); 
    digitalWrite(_pin, HIGH);

instead, but this is no real solution. Does OUTPUT_PULLUP have the same effect? If so, could you please define an alias so that the original library can be used again. I am using version 0.0.3, installed by the board manager on Arduino IDE 1.8.10.

Heltec-Aaron-Lee commented 4 years ago

ASR650x is a PSoC 4000 series based core, the GPIOs only support with the following status: image

joergkeller commented 4 years ago

I see. In contrast, Arduino defines the following pin modes: INPUT, OUTPUT, or INPUT_PULLUP. So the question is how to implement INPUT_PULLUP. My understanding of the datasheets is that the pin could be set to OUTPUT_PULLUP, then (digitalWrite?) to 1 which activates the pull-up followed by analogRead. But I'm a software engineer and if this really works (needed delays to stabilize?), I don't know.

Bwooce commented 4 years ago

Hey Joerg, what's happening is that other Arduino boards support connecting an internal resistor to feed voltage into the pin, but fed through a high enough resistance that you can drag them low by shorting to ground (and not much current flows due to the high resistance). This gives a more reliable on/off indication as spurious momentary high voltages can occur on LOW->HIGH pins aka INPUT, which gives false signals, but it'd be very uncommon to randomly short to ground (INPUT_PULLUP).

These resistors do not appear to exist on the PSoC 4000 chips. You can't turn them on as they're not in the silicon for inputs (they are for outputs, but I'm intrigued by the PULLUP_PULLDOWN one). You can implement the PULLUP the same on the CubeCell by using an external resistor fed from a 3v3 pin, which may not be the answer you want but...it'd work (and you'd change the code to just use INPUT).

Clearer?

joergkeller commented 4 years ago

Thanks @Bwooce, I understand the idea behind pullup/down. I was initially also confused by the PSoC OUTPUT_XXX rather than INPUT_PULLUP. But if you look at the drive modes (PSoC4 Using GPIO Pins, page 8), the "output mode" connects the resistor (they do appear to exist!) to VDD/GND, but the "In" latch is active at the same time. image

Bwooce commented 4 years ago

Sorry for talking down to you @joergkeller :-) Wonderful docs you found, I didn't do as well.

So the obvious question, if you specify a pin as OUTPUT_PULLUP or OUTPUT_PULLUP_PULLDOWN, does it work properly as an input? The diagram says it should, as you say.

lnlp commented 4 years ago

Is there any clarity and progress about this?

joergkeller commented 4 years ago

I think I have a solution but need to test it first. Maybe I have time this evening.

joergkeller commented 4 years ago

The modes can be used to enable resistive pull up/down followed by digitalRead. This works, I've tested it on an digital pin (e.g. GPIO0), but not on the analog pin.

// setup
pinMode(pin, OUTPUT_PULLUP);
digitalWrite(pin, HIGH);
// later, e.g. loop
Serial.println(digitalRead(PIN));

But that is only half of what I need. Some libraries use pinMode(pin, INPUT_PULLUP resulting in compile problem. Instead of patching each library I would really be very convenient if the PSoC 4000 firmware would define INPUT_PULLUP and INPUT_PULLDOWN and implement it with something like above.

As a workaround I've created the following macro, but I'm sure there's a better way:

#define INPUT_PULLUP   ((PINMODE)98)
#define INPUT_PULLDOWN ((PINMODE)99)
#define pinMode(pin,mode) ({        \
  if(mode==INPUT_PULLUP){           \
    pinMode(pin, OUTPUT_PULLUP);    \
    digitalWrite(pin, HIGH);        \
  }else if(mode == INPUT_PULLDOWN){ \
    pinMode(pin, OUTPUT_PULLDOWN);  \
    digitalWrite(pin, LOW);         \
  }else                             \
    pinMode(pin, mode);             \
})

Any macro expert to rescue me?

joergkeller commented 4 years ago

An improved set of macros that are probably more efficient:

#define pinMode(pin,mode) PINMODE_ ## mode(pin)
#define PINMODE_ANALOG(pin) pinMode(pin,ANALOG)
#define PINMODE_INPUT(pin) pinMode(pin,INPUT)
#define PINMODE_OUTPUT_PULLUP(pin) pinMode(pin,OUTPUT_PULLUP)
#define PINMODE_OUTPUT_PULLDOWN(pin) pinMode(pin,OUTPUT_PULLDOWN)
#define PINMODE_OD_LO(pin) pinMode(pin,OD_LO)
#define PINMODE_OD_HI(pin) pinMode(pin,OD_HI)
#define PINMODE_OUTPUT(pin) pinMode(pin,OUTPUT)
#define PINMODE_OUTPUT_PULLUP_PULLDOWN(pin) pinMode(pin,OUTPUT_PULLUP_PULLDOWN)
#define PINMODE_INPUT_PULLUP(pin) ({pinMode(pin,OUTPUT_PULLUP); digitalWrite(pin,HIGH);})
#define PINMODE_INPUT_PULLDOWN(pin) ({pinMode(pin,OUTPUT_PULLDOWN); digitalWrite(pin,LOW);})

I can create a pull-request for that, but can someone please make some additional tests? https://github.com/HelTecAutomation/ASR650x-Arduino/pull/53