Pull-up resisters not working on Mega 2560

Any ideas why pull-ups do not seem to function on a Mega?
When open it yields 0 or "Closed". If I place 5V on pin 31 it will yield "Open"

Abbreviated Code:

#define denThermostate 31

pinMode(denThermostate, INPUT_PULLUP);

lcd.print("Den     = ");
        if (digitalRead(denThermostate) == 0)
          lcd.print ("Closed");
        else
          lcd.print ("Open");

post a wiring diagram

Perhaps that pin has been damaged, or you have miswired it.

Try another digital pin, and just print the results of digitalRead().

I've actually tried a new mega with same results. No external wiring. May need try some basic code.

Does the same on blank PCB.

see reply #3. Also don't post snippets, post your complete, entire sketch.

I have no idea what you mean. What does the same? How can a blank PCB do anything?

How is it possible to test the input if there is no wiring?

That's exactly what you coded.

lcd.print("Den     = ");
        if (digitalRead(denThermostate) == 0) // when grounded...
          lcd.print ("Closed"); // print "Closed"
        else // when connected to 5volt...
          lcd.print ("Open"); // print "Open"

You don't have to connect it to 5volt to print "Open",
because the internal pull up will already do that for you.
Just connect the switch between pin and ground.
Leo..

It gets confusing. Both LEDs and switches/buttons can be wired and programmed right side up or upside down.

Often ppl will help themselves and leave one place to fix, or modify if wiring changes, the sense of things, viz:

// at the top, place

const byte OPEN = HIGH;
const byte CLOSED = LOW;


// then always use the constants

  lcd.print("Den     = ");
  if (digitalRead(denThermostate) == CLOSED)
    lcd.print ("Closed");
  else
    lcd.print ("Open");

Or use better names for HIGH and LOW that speak to the condition you are reading.

 const byte CALLING_FOR_HEAT = LOW;

a7

Pullups DO work on the Mega 2560.

The OP seems unable provide the information needed to understand the real problem.

That has never happened before :sunglasses:

2 Likes

That might be handy or needed for large/complicated programs,
but at some stage you need to understand inverted logic (like in the TTL days).
Leo..

Post 11 answers your question.

Thanks. I'll make a point of looking into that one day.

a7

That's an excellent idea to make my code more readable. I'll rewrite some code.

1 Like

For those that like root canal work. I could probably spend a month explaining what I'm doing here and that is the reason why I did not attach all the code. But you are exactly right, the error was in code and not obvious at first. It was code left in before some changes in outputs were made. Please excuse the crappy coding, but it is my first attempt at C++ or anything to do with Arduino. This is being used as a remote satellite controller via RS485 to adjust radiant floor temperatures with a stepper mixing valve, controlling 3 zone valves and three pumps. It incorporates an offline mode in case the main controller wigs out. One or two suggestion on coding would be welcomed. I am a beginner. I left the bug for your entertainment. Let's see how you do with all the code. I can send the schematic for the piggy packed expansion PCB. I admit it was a bugger for me to find.

/*
  NEMA 17 Bipolar Stepper with A4988/TCM2208 Driver
  Set TCM2208  Current limit for TCM2208 is 1.2 Amp. Max I for motor is 1.5
  https://wiki.fysetc.com/TMC2208/#pin-functions
  Set Static Vref to 1.4 -1.5V less 10% = 1.35V

  DS18B20 temperature sensor (https://arduino-tutorials.net)

  // Define Constants
  // Connections to A TCM2208


******* LCD CONTROL *******
  http://www.arduino.cc/en/Tutorial/LiquidCrystal
  The circuit:

   LCD RS pin to digital pin 7
   LCD Enable pin to digital pin 8
   LCD D4 pin to digital pin 9
   LCD D5 pin to digital pin 10
   LCD D6 pin to digital pin 11
   LCD D7 pin to digital pin 12
   LCD R/W pin 5 to ground
   LCD VSS pin 1 to ground
   LCD VDD or VCC pin to 5V
   10K resistor:
   ends to +5V and ground
   wiper to LCD VO pin (pin 3)
*/
// Include the LCD library code:

#include <Streaming.h>

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);


// Libraries for the 1-wire DS18B20 temperature sensor
#include <OneWire.h>
#include <DallasTemperature.h>

//URL: http://forum.arduino.cc/index.php?topic=356253
#include "CountDown.h"
CountDown CD;// Count Do
CountDown KACD;// Keep Alive
//https:///oreil.ly/PJWJR Page 128 Arduino Cookbook
#include <Streaming.h>

/*-----( Declare Constants and Pin Numbers )-----*/

#define sSerialTxControl 4   //RS485 Direction control
#define rS485Transmit    HIGH
#define rs485Receive     LOW
#define turnOnBacklight 6
#define Pin13LED  13      // To blink serial in data
#define zone1    22
#define zone2    23
#define zone3    24
#define floorPump 25
#define DHWPump   26
#define boilerRelay 27
#define convector 28
#define Spare     29
#define denThermostate 31
#define bedroomThermostate 32
#define kitchenThermostate 33
#define zoneSwitch 34
#define endSensor 35       // Limit Closed Stepper uses Pullup Resistor. Normally Grounded
#define limitOpen 36       // Limit Open Stepper
#define DHWSwitch 37




/*-----( Declare Variables )-----*/
// Motor steps per rotation and connected pins
const int STEPS_PER_REV = 200;
const int dirPin = A1;  // Direction
const int stepPin = A0; // Step
int leadScrewRevolutions = 107;// Must move valve 4 1/8" or 25 revolutions per inch. Total steps 21400
int stepCount = (STEPS_PER_REV * leadScrewRevolutions);
short LF = 10; //ASCII Linefeed
int outputSelect = 0;
int keepAliveTime = 1;// Minutes
int displayBlankTime = 10;// Minutes
bool offLine = false;
const byte OPEN = HIGH;
const byte CLOSED = LOW;

// bool homePosition = false; //Not Used

String stepDirection = "";
float tempDelta = 0; // Initialize. May not need
float setTemp = 27; //Default Start Temp
float temperature = 0.0;

int oneWireBus = 5;                    // 1-wire pin// variable to store the measured temperaturevariabele (float = floating point number)
const int NUMBER_OF_FIELDS = 3;
float values[NUMBER_OF_FIELDS];

/*-----( Declare objects )-----*/
OneWire oneWire(oneWireBus);            // 1-wire instance on the oneWireBus pin
DallasTemperature sensors(&oneWire);    // give the OneWire instance as parameter to the DallasTemperature library.
// pass the address (Pointer) and not the contents of the variable itself, we use &.

// initialize the library with the numbers of the interface pins. Use when not employing Serial LCD control <LiquidCrystal_I2C.h>
// LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


void setup()
{
  // set up the LCD's number of columns and rows:
  lcd.init();
  lcd.backlight();
  lcd.setCursor(2, 0);
  lcd.print("Harmony Controls");
  lcd.setCursor(1, 2);
  lcd.print("Initiating Stepper");

  // Countdown 10 minute for display backlight turn off
  CD.start(0, 0, displayBlankTime, 0); //Days,Hours,Min,Sec Initial lcd on time

  //Countdown for Uptairs Computer PWR Fail
  KACD.start(0, 0, keepAliveTime, 0); //Initial lcd on time

  // Setup the pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  //pinMode(LED_BUILTIN, OUTPUT);

  //Output config
  pinMode(endSensor, INPUT_PULLUP); // May not need pullup if using mechanical Sw
  pinMode(limitOpen, INPUT_PULLUP); // May not need pullup if using mechanical Sw
  pinMode(zone1, OUTPUT);
  pinMode(zone2, OUTPUT);
  pinMode(zone3, OUTPUT);
  pinMode(convector, OUTPUT);
  pinMode(DHWPump, OUTPUT);
  pinMode(boilerRelay, OUTPUT);
  pinMode(floorPump, OUTPUT);
  pinMode(DHWSwitch, INPUT_PULLUP);
  pinMode(kitchenThermostate, INPUT_PULLUP);
  pinMode(bedroomThermostate, INPUT_PULLUP);
  pinMode(denThermostate, INPUT_PULLUP);
  pinMode(turnOnBacklight, INPUT_PULLUP);
  pinMode(zoneSwitch, INPUT_PULLUP);

   DDRC = B11111111; // set PORTC (digital 7~0) to outputs
  DDRA = B11111111; // set PORTA (digital 7~0) to outputs

  // Configure Serial1
  pinMode(Pin13LED, OUTPUT); //Shows input data received
  pinMode(sSerialTxControl, OUTPUT); //Direction Control Pin for Max485

  // Begin built in Serial communication at a baud rate of 9600:
  Serial.begin(9600); // set the data rate

  // Begin built in Serial1 communication at a baud rate of 9600:
  Serial1.begin(9600); // set the data rate for Max 485
  digitalWrite(sSerialTxControl, rs485Receive);  // Init Transceiver direction to Receive (LOW)



  // Serial.println("Bas on Tech - 1-wire temperature sensor"); // print message to serial monitor
  // sensors.begin();                      // start with reading the sensor
  // Reset stepper to home position
  findHome();
}

void loop() {
  temperature = CallTemperature();

  //if (homePosition) // Heating disabled or too low. Not used
  // setTemp = 0;// not used

  tempDelta = setTemp - temperature;

  if (temperature > setTemp + .1)
  {
    digitalWrite(dirPin, HIGH); // Set Directing to in
    closeValve();
  }
  if (temperature < setTemp - .1)
  {
    digitalWrite(dirPin, LOW); // Set to open direction to out
    openValve();
  }
  serial1Check();

  if (KACD.remaining() <= 0)// && offLine == false ) // Reached end of Keep Alive Time
  {
    PORTA = 0;  // Clear all outputs once (PORTA = 0) before going into Offline Mode
    PORTC = 0; 
    offLine = true;
  }
  if (offLine == true)
    thermostateMode();
}

/******* OPEN VALVE (Out)  *********/
void openValve() {
  for (int i = 0; i <= int(tempDelta * 10); i++) // Number of loops decreases as temp get closer to desired
    if (stepCount <= (STEPS_PER_REV * leadScrewRevolutions))
    {
      stepCount++;
      digitalWrite(stepPin, HIGH);
      delay(1);
      digitalWrite(stepPin, LOW);
    }
  Serial.println("");
  Serial.println("Opening ");
  Serial.print("Temperature Delta =  "); Serial.println(tempDelta); // Temperature differentual (Desired - Actual)
  //printData(); //Sub to print all data
  stepDirection = "Open";

  int limitOpenSensor = digitalRead(limitOpen); // Look to see if end stop sensor reached
  if (limitOpenSensor == HIGH) // Change to LOW if using pullup resister
  {
    stepCount = 21401; // Reset stepcount to 21401
    Serial << "" << "Open End Sensor Reached" << endl;
  }
}

/*******  CLOSE VALVE (IN)  *********/
void closeValve() {

  for (int i = 0; i <= int((tempDelta * -1) * 10); i++) // Number of loops decreases as temp get closer to desired
    if (stepCount >= 0)
    {
      stepCount--;
      digitalWrite(stepPin, HIGH);
      delay(1);
      digitalWrite(stepPin, LOW);
    }
  Serial.println("");
  Serial.println("Closing ");
  Serial.print("Temperature Delta =  "); Serial.println(tempDelta); // Temperature differentual (Desired - Actual)

  //printData(); //Sub to print all data
  stepDirection = "Close";

  int endStopSensor = digitalRead(endSensor); // Look to see if end stop sensor reached
  if (endStopSensor == HIGH) // Change to LOW if using pullup resister
  {
    stepCount = 0; // Reset stepcount to 0
    Serial << "" << "End Stop Reached" << endl;
  }
}

/*******  CALCULATE TEMPERATURE & Check on LCD Off Timer *********/
float CallTemperature() {
  sensors.requestTemperatures();          // read the temperature of all 1-wire sensors connected to the 1-wire bus
  float temp = sensors.getTempCByIndex(0);      // get the temperature of the first sensors in Celcius (lists start with 0 not 1)
  // temp = sensors.getTempFByIndex(0);   // get the temperature of the first sensors in Fahrenheit (lists start with 0 not 1)

  Serial << "Temperature = " << temp << " \xC2\xB0" << "C" << endl;
  Serial << "Step Count = " << stepCount << endl;

  LCDControl();
  return (temp);
}

void LCDControl() {

  // Check if the (turnOnBacklight) pushbutton is pressed.
  if (digitalRead(turnOnBacklight) == LOW)
    CD.start(0, 0, displayBlankTime, 0);  // Reset Backlight timer to 10 min

  if (CD.remaining() > 0 && CD.isRunning() ) // Time on timer > 0 and Timer runing
  {
    lcd.backlight();//Turn on
  }
  else
  {
    lcd.noBacklight();//Turn off
    outputSelect = 27; // skip Lcd output routine
  }

  outputSelect ++;

  switch (outputSelect)
  {
    case 1:
      lcd.clear();
      lcd.print("Zone #1    = ");
      lcd.print(digitalRead(zone1));// Zone Valve #1

      lcd.setCursor(0, 1);//Zone Valve #2
      lcd.print("Zone #2    = ");
      lcd.print(digitalRead(zone2));// Zone Valve #2

      lcd.setCursor(0, 2);
      lcd.print("Zone #3    = ");
      lcd.print(digitalRead(zone3));// Zone Valve #3

      lcd.setCursor(0, 3);
      lcd.print("Floor Pump = ");
      lcd.print(digitalRead(floorPump));//Downstairs Floor Pump
      break;

    case 8:
      lcd.clear();
      lcd.print("DHW Pump       = ");
      lcd.print(digitalRead(DHWPump));//DHW Pump

      lcd.setCursor(0, 1);
      lcd.print("Boiler Relay   = ");
      lcd.print(digitalRead(boilerRelay)); //Boiler

      lcd.setCursor(0, 2);
      lcd.print("Register Pump  = ");
      lcd.print(digitalRead(convector));//Register Pump

      lcd.setCursor(0, 3);
      lcd.print("Spare 29       = ");
      lcd.print(digitalRead(convector));// Spare
      break;


    case 15: //Required Temp & Actual Temperature
      lcd.clear();
      lcd.print("Req Temp    = ");
      lcd.print(setTemp);// Requested temp

      lcd.setCursor(0, 1);
      lcd.print("Curent Temp = ");
      lcd.print(temperature);// Current Temp

      lcd.setCursor(0, 2);
      lcd.print("Step Count  = ");
      lcd.print(stepCount);// Step Count

      lcd.setCursor(0, 3);// Stepper Direction
      lcd.print("Direction   = ");
      lcd.print(stepDirection);
      break;



    case 23: //Required Temperature & Actual Temperature
      lcd.clear();
      lcd.print("Display CD = ");
      lcd.print(CD.remaining()); lcd.print(" Sec");// Requested temp

      lcd.setCursor(0, 1);
      lcd.print("Keep Alive = ");

      if (KACD.remaining() >> 0) // Keep Alive Timer time remaining
      {
        lcd.print(KACD.remaining()); lcd.print(" Sec"); // Keep Alive Countdown
      }
      else
      {
        lcd.setCursor(0, 1);
        lcd.print("OFF Line           ");
      }
      lcd.setCursor(0, 2);
      lcd.print("Zone Switch = ");

      if (digitalRead(zoneSwitch) == CLOSED)// Zone 1-3 (True = open)
        lcd.print ("Closed");
      else
        lcd.print ("Open");
      lcd.setCursor(0, 3);//
      lcd.print("DHW  Switch = ");

      if (digitalRead(DHWSwitch) == CLOSED)// DHW Switch
        lcd.print ("Closed");
      else
        lcd.print ("Open");

      //lcd.print(stepDirection);
      break;

    case 31:

      if (offLine == true)
      {
        lcd.clear();
        lcd.print("Kitchen = ");
        if (digitalRead(kitchenThermostate) == OPEN) // Kitchen Thermostate open
        {
          lcd.print ("Open");
          Serial.println("Kitchen Thermostate = ");
          Serial.println("Open");
          Serial.println(kitchenThermostate);
        }
        else
        {
          lcd.print ("Closed");
          Serial.println("Kitchen Thermostate = ");
          Serial.println("Closed");
          Serial.println(kitchenThermostate);
        }

        lcd.setCursor(0, 1);
        lcd.print("Bedroom = ");
        if (digitalRead(bedroomThermostate) == OPEN) // Bedroom Thermostate closed
          lcd.print ("Open");
        else
        {
          lcd.print ("Closed");
          Serial.println("Bedroom Thermostate = ");
          Serial.println("Closed");
        }

        lcd.setCursor(0, 2);
        lcd.print("Den     = ");
        if (digitalRead(denThermostate) == OPEN) // Den Thermostate closed
          lcd.print ("Open");
        else
        {
          lcd.print ("Closed");
          Serial.println("Den Thermostate = ");
          Serial.println("Closed");
        }
      }
      else
       outputSelect = 0;
        break;

    case 39:
      outputSelect = 0;
      break;
  }
}

/******* STEPPER TO HOME SUB  *********/
void findHome() {

  // ---- SET VALVE TO CLOSE -----
  digitalWrite(dirPin, HIGH);

  //Serial.println("Finding Home"); Serial.println("");
  Serial << "" << "Finding Home" <<  endl;
  Serial.println("");

  // stepCount = 21400 // *******Un-rem this when finnished to allow home switch to be found on reset************

  // Turn stepper one rotation (In)
  for (; stepCount >= 0; stepCount--)
  {
    digitalWrite(stepPin, HIGH);
    serial1Check(); // Check for serial1 data
    delayMicroseconds(500);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(500);

    int endStopSensor = digitalRead(endSensor);
    if (endStopSensor == HIGH)
    {
      stepCount = 0; // Clear step count
      Serial << "" << "End Stop Reached" <<  endl;
      Serial.println("");
    }
  }
  loop();
}

/******* READ SERIAL PORT FOR DATA COMMAND FROM XOJO *********/
void serial1Check() {
  if (Serial1.available())
  {
    if (Serial1.read() == 'H') {

      digitalWrite(Pin13LED, HIGH);  // Show activity on Pin 13 LED

      /******* Set Read Values *********/
      Serial.println("");
      lcd.begin(20, 4);


      for (int i = 0; i < NUMBER_OF_FIELDS; i++)
      {
        values[i] = Serial1.parseFloat();
      }
      //Display the values in comma-separated format
      Serial.print(values[0]); // first value

      //Print the rest of the values with leading comma
      for (int i = 1; i < NUMBER_OF_FIELDS; i++)
      {
        Serial.print(","); Serial.print(values[i]);
      }
      // Set the cursor to column 0, line 1
      // (note: line 1 is the second row, since counting begins with 0):

      lcd.print(int(values[0])); lcd.print(" "); lcd.print(values[1] ); lcd.print(" "); lcd.print(int(values[2]));

      /******* Set Outputs *********/
      PORTA = values[0];

      /******* Set Temperature *********/
      setTemp = values[1];
      setTemp = constrain  (setTemp, 0, 46);// Max temp is 46 C or 115 F
      Serial.println("");
      Serial << "Constained Value =  " << setTemp << " \xC2\xB0" << "C" << endl;
      Serial.println("");

      /******* Reset Valve *********/
      if (values[2] == 1) //1 = Reset Valve
        findHome(); //Do not need brackets if one liner

      /******* Return Data *********/
      if (values[2] == 2) //2 = Return data
        ReturnDataToXOJO(); //Do not need brackets if one liner

      /******* Keep Alive *********/
      if (values[2] == 3) //3 = Keep Alive
        
{
      KACD.start(0, 0, keepAliveTime, 0); // Keep alive signal from XOJO (10 Min)
      offLine = false;
     ReturnDataToXOJO(); //Do not need brackets if one liner
}

      /******* Stepper Disabled ********* Not Used
        if (values[2] == 4) //4 = Home position (Stepper Disabled)
        homePosition = true;

        /******* Stepper Enabled ********* Not Used
        if (values[2] == 5) //5 = Stepper Enabled. Not used
        homePosition = false;
      */

      digitalWrite(Pin13LED, LOW);  // Clear pin 13
    }
  }
}

/******* Retrun data to XOJO *********/
void ReturnDataToXOJO()
{
  Serial1.readString();
  // Send data out to XOJO through 485 serial
  digitalWrite(sSerialTxControl, rS485Transmit);  // Enable RS485 to Transmit
  Serial1.print(setTemp);
  Serial1.print(",");
  Serial1.print(temperature);
  Serial1.print(",");
  Serial1.print(tempDelta);
  Serial1.print(",");
  Serial1.print(stepCount);
  Serial1.print(",");
  Serial1.print(digitalRead(zone1));// Zone Valve #1
  Serial1.print(",");
  Serial1.print(digitalRead(zone2));// Zone Valve #2
  Serial1.print(",");
  Serial1.print(digitalRead(zone3));// Zone Valve #3
  Serial1.print(",");
  Serial1.print(digitalRead(floorPump));// Downstairs Floor Pump
  Serial1.print(",");
  Serial1.print(digitalRead(DHWPump));// DHW Pump
  Serial1.print(",");
  Serial1.print(digitalRead(boilerRelay));// Boiler
  Serial1.print(",");
  Serial1.print(digitalRead(convector));// Upstairs register Pump (Convector)
  Serial1.print(",");
  Serial1.print((digitalRead(zone1) * 1) + (digitalRead(zone2) * 2) + (digitalRead(zone3) * 4) + (digitalRead(floorPump) * 8) + (digitalRead(DHWPump) * 16) + (digitalRead(boilerRelay) * 32) + (digitalRead(convector) * 64));
  Serial1.print(",");

  delay(100);
  digitalWrite(sSerialTxControl, rs485Receive);  // Disable RS485 Transmit. Set to Receive
  delay(100);
}


/******* XOJO Fail Mode *********/
void thermostateMode() {
  Serial.println ("Off Line");

  if ((digitalRead(DHWSwitch) == LOW) || (digitalRead(zoneSwitch) == LOW)) // DHW switch (37) closed or any zone open switch (2)
    digitalWrite(boilerRelay, 1); //Boiler Relay Turn On
  else
    digitalWrite(boilerRelay, 0); //Boiler Relay Turn Off

  if (digitalRead(zoneSwitch) == LOW) // Any zone needs heat and is open which closes zone switch (Pin 2)
  {
    setTemp = 46; //Set Mixing Valve Temp to 46C or 115F
    digitalWrite(floorPump, 1); //  Floor Pump Turn On
  }
  else
  {
    Serial.print ("Zone Switch  = ");
    Serial.println(digitalRead(zoneSwitch));
  }
  setTemp = 25;// Set temp to 25C
  digitalWrite(floorPump, 0); //  Floor Pump Turn Off

  if (digitalRead(denThermostate) == HIGH) //Den Thermostate Requirement (pulled to ground on closure)
    digitalWrite(convector, 0); // Upstairs Floor Register Pump Turn off
  else
    digitalWrite(convector, 1); // Upstairs Floor Register Pump Turn On

  if (digitalRead(bedroomThermostate) == HIGH) //Bedroom Thermostate Requirement (pulled to ground on closure)
  {
    digitalWrite(zone2, 0); //Zone Valve #2 Turn Off
    digitalWrite(zone3, 0); //Zone Valve #3 Turn Off
  }
  else
  {
    digitalWrite(zone2, 1); //Zone Valve #2 Turn On
    digitalWrite(zone3, 1); //Zone Valve # 3 Turn On
  }

  if (digitalRead(kitchenThermostate) == HIGH) //Kitchen Thermostate Requirement (pulled to ground on closure)

    // digitalWrite(zone1, 0); //Zone Valve #1  Turn Off
    //else
    //digitalWrite(zone1, 1); //Zone Valve #2 Turn On

    if (digitalRead(DHWSwitch) == HIGH) //DHW SW
      digitalWrite(DHWPump, 0); //DHW Pump Turn Off
    else
      digitalWrite(DHWPump, 1); //DHW Pump Turn On
}

I'm curious why the unsigned byte is use in ```
const byte CLOSED = LOW;

Do other data types work?

Actually, an enum is the best way to handle that. I don't have one handy to show you, but...

Hmmm. Do other types work? Well, certain criterion do apply. In this case, it must be able to represent a binary choice of two states without error. The 'byte' type is often used for binary variables because it uses the least memory on most machines.

Individual bits are not usually rapidly processed on most machines. However some do support bit operations in hardware, and you can always pack 8 bits of information into a byte if you can affort to wait a few CPU cycles for it

So the goal in your choice is to be memory efficient, since int also works. Got it.