IO digital with low power

I am working on a project that includes activating two relays through two digital outputs with a MEGA board.

The software works perfectly on the D42 and D44 outputs, it detects the outputs at 1 when it corresponds.

The problem is that when the logic state of D42 or D44, according to Arduino, is HIGH, the voltage that I measure at the digital IO with a FLUKE 115 multimeter is less than 2V, insufficient to drive a UDN2981A driver.

The supply voltage of the MEGA board comes from an external regulator LM7805, and the measurement is 4.8V,

I’m doing something wrong and can’t find a way to find out, so I would appreciate any help.

void setup() {
Serial.begin(9600);
Serial.setTimeout(50);
rtc.begin();

lcd.init();
lcd.backlight();
lcd.clear();

pinMode(pin_button_clock_up, INPUT_PULLUP);
pinMode(pin_button_clock_mode, INPUT_PULLUP);
pinMode(pin_button_clock_down, INPUT_PULLUP);
pinMode(pin_button_antennas_mode, INPUT_PULLUP);
pinMode(pin_relay_hexbeam, OUTPUT);
pinMode(pin_relay_aperiodic, OUTPUT);

digitalWrite(pin_relay_hexbeam, LOW);
digitalWrite(pin_relay_aperiodic, LOW);

check_active_rig ();
check_active_band ();
check_active_antenna ();

if (active_rig == power_on) {
show_active_band ();
show_active_antenna ();
} else {
active_relays_antennas (LOW, LOW);
show_rig_off ();
}
process_date();
}

Hi,
Can you post a circuit diagram please?

Have you written some simple code that JUST switches D42 and D44 to check?

Thanks… Tom… :smiley: :+1: :coffee: :australia:

1 Like

Uploading: esquema-conexiones-1.jpg…

IOs are D42 and D44 instead of D32 and D34. And I not tried with a dedicated code.

void active_relays_antennas (bool hex, bool ape) {  //Switch the antenna relays 
  digitalWrite(pin_relay_hexbeam, hex);             //the variables hex and ape contain HIGH o LOW    
  digitalWrite(pin_relay_aperiodic, ape);           //if one or the other is the active antenna
}

That makes little sense.
You need to post all your code for it to make any sense. You are setting names to be input or output. We can not see what pins these actually correspond to. With only the setup function we can not tell what you are doing with these pins.

My apologies

#include <Wire.h>                                                                                                                             #include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <WString.h>
#include "defines.h"

/*
 * Procedimiento y funciones del reloj
 */

String name_of_month(month_name m) {  //Recibe un valor de variable month_name y devuelve el valor
  switch (m) {                        //que identifica en la definiciĂłn correspondiente del mes
    case january:   return month_01;  //en el lenguaje seleccionado (#define LANGAUGE_
    case february:  return month_02;
    case march:     return month_03;
    case april:     return month_04;
    case may:       return month_05;
    case june:      return month_06;
    case july:      return month_07;
    case august:    return month_08;
    case september: return month_09;
    case october:   return month_10;
    case november:  return month_11;
    case december:  return month_12;
   }
  }

String name_of_the_day_of_the_week(dow_name d) { //Recibe un valor de variable dow (DayOfWeek) y devuelve
  switch (d) {                                   //el valor que identifica en la definiciĂłn correspondiente
    case sunday:    return week_7;               //del dĂ­a de la semana en el lenguaje seleccionado
    case monday:    return week_1;
    case tuesday:   return week_2;
    case wednesday: return week_3;
    case thusday:   return week_4;
    case friday:    return week_5;
    case saturday:  return week_6;
  }
}

int calc_time_offset(DateTime dt_utc) {               //Rebibe una instancia de la clase DateTime y devuelve
  byte last_day_before_last_monday = 24;              //el lapso de tiempo entre la hora UTC y local en
  byte hour_of_change = 2;                            //en el huso horario de España horario de invierno
  int winter_offset = 3600;     //1 hora = 3600seg    //en periodo de verano e invierno    
  int summer_offset = 3600 * 2; 
  month_name number_month = dt_utc.month();
  dow_name dow_number = dt_utc.dayOfTheWeek();

  if (number_month > march && number_month < october) { //Si el mes está entre marzo y octubre
    return summer_offset;
  }

  if (number_month > october || number_month < march) { //Si el mes stá entre octubre y el siguiente marzo
    return winter_offset;
  }

  if (number_month == march) {                          //Si el mes es marzo y..
    if (dt_utc.day() < last_day_before_last_monday) {   //el dĂ­a es inferior a 24 (ultimo dĂ­a que puede ser domingo
      return winter_offset;                             //comĂąn a todos los meses
    } else {
      if (dow_number == sunday) {                       //Si el dĂ­as es posterior al 24 y es domingo
        if (dt_utc.hour() < hour_of_change) {
          return winter_offset;
        } else {
          return summer_offset;
        }
      } else {                                          //Si 24 - dĂ­a dĂ­a del mes + dia de la semana >= 0 
        if (last_day_before_last_monday - dt_utc.day() + dow_number >= 0) { //no ha cambiado el periodo
          return winter_offset;
        } else {
          return summer_offset;
        }
      }
    }
  }

  if (number_month = october) {                       //Mismo cálculo que para marzo
    if (dt_utc.day() < last_day_before_last_monday) {
      return summer_offset;    
    } else {
      if (dow_number == sunday) {
        if (dt_utc.hour() < hour_of_change) {
          return summer_offset;
        } else {
          return winter_offset;
        }
      } else {
        if (last_day_before_last_monday - dt_utc.day() + dow_number >= 0) {
          return summer_offset;
        } else {
          return winter_offset;
        }
      }
    }   
  }
}

byte check_next_day() {                       //Detecta si ha cambiado de dia para sacar la fecha al display
  DateTime dt_utc = rtc.now();
  int time_offset = calc_time_offset(dt_utc);
  DateTime dt_local = dt_utc.unixtime() + time_offset;
  bool is_next_day = dt_local.hour() == 0 && dt_local.minute() == 0 && dt_local.second() == 0;

  if (is_next_day) {
    delay(1000);
  }
  return is_next_day;
}

void show_invalid_data() {        //Indica que hay error si los datos introducidos en el monitos serie
  lcd.clear();                    //son incorrectos
  lcd.setCursor(0, 0);
  lcd.print("  DEBE INTRODUCIR");
  lcd.setCursor(0, 1);
  lcd.print("  UNA FECHA VALIDA");
  lcd.setCursor(0, 2);
  lcd.print("        Y/O");
  lcd.setCursor(0, 3);
  lcd.print("    HORA VALIDOS");
  delay(2000);
  lcd.clear();  
}

bool button_pressed (int button) {      //Devuelve TRUE (1) si ha sido pulsado el boton button
  bool bp = digitalRead(button) == LOW;
  if (bp) {
    delay(250); 
  }
  return bp;
}

void show_end_of_process_display () {   //Prsenta en el display la opciĂłn grabar en la puesta en hora por botones
  lcd.setCursor(0, 0);
  lcd.print("B.SUP(+)  = GRABAR ");
  
  lcd.setCursor(0, 1);
  lcd.print("B.INF(-) = SUSPENDER"); 
}

void switch_clock_mode() {
  if (cm_mode == mode_end_of_process) { //Cambia secuencialmente el dato de ajuste de fecha y hora
    cm_mode = mode_normal;              //Año, mes, día, hora, minuto
  } else {
    cm_mode = cm_mode + 1;
  }
}

void clear_clock_display() {            //Deja en blanco las tres p`rimeras lĂ­neas del display
  lcd.setCursor(0, 0);
  lcd.print("                    ");
  lcd.setCursor(0, 1);
  lcd.print("                    ");
  lcd.setCursor(0, 2);
  lcd.print("                    "); 
}

void show_settings_label (String s_label) { //Muestra en el display la etiqueta del dato a ajustar
  lcd.setCursor(0, 0);
  lcd.print("       ");
  lcd.setCursor(0, 0);
  lcd.print(s_label);  
}

void show_settings_data(int i_data) {     //Muestra el nuevo ajuste de cada dato
  lcd.setCursor(9, 0);
  lcd.print("    "); 
  lcd.setCursor(9, 0);
  lcd.print(i_data, DEC);  
}

void show_set_date_time(int yr, int mt, int dy, int hr, int me) {   //Muestras los nuevos datos para el ajuste
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  lcd.setCursor(0, 2);
  lcd.print(String(dy) + "/" + String(mt) + "/" + String(yr));
  
  lcd.setCursor(11, 2);
  lcd.print("     ");
  lcd.setCursor(11, 2);
  lcd.print(String(hr) + ":" + String(me));
}

int month_bounds(int mt) {  //Modifica el mes en los lĂ­mites
  if (mt > 12) {
    return 1;
  } else if (mt == 0) {
    return 12;
  } else {
    return mt;
  }
}

int day_bounds(int yr, int mt, int dy) {  //Modifica los dĂ­as del mes en los lĂ­mites 
  int day_top = 31;
  
  if (mt == february) {
    if (leap_year(yr)) {
      day_top = 29;
    } else {
      day_top = 28;
    }
  } else if (mt == april || mt == june || mt == september || mt == november) {
    day_top = 30;
  }

  if (dy > day_top) {
    return 1;
  } else if (dy == 0) {
    return day_top;
  } else {
    return dy;
  }
}

int hour_bounds(int hr) {   //Modifica la hora del dĂ­a en los lĂ­imites
  if (hr > 23) {
    return 0;
  } else if (hr < 0) {
    return 23;
  } else {
    return hr;
  }
}

int minute_bounds(int mi) { //Modifica los lĂ­mites de los minutos
  if (mi > 59) {
    return 0;
  } else if (mi < 0) {
    return 59;
  } else {
    return mi;
  }
}

bool leap_year (int y) {        //Calcula si el año actual es bisiesto
  return y%4 == 0 && y%10 != 0;
}

bool check_valid_data(int dy, int mt, int yr, int mi, int se) { //Comprueba que la fecha y hora ropuesta para
  int days_offset = 0;                                          //ajustar el reloj desde el monitor serie 
                                                                //son correctos
  if (mt == april || mt == june || mt == september || mt == november) {
    days_offset = 1;
  } else if (mt == february) {
    if (leap_year(yr)) {
      days_offset = 2;
    } else {
      days_offset = 3;
    }
  }

  if (mt <= january || mt > december) {
    return false;
  } else if (dy <= 0 || dy + days_offset > 31) {
    return false;  
  } else if (mi < 0 || mi > 59) {
    return false;
  } else {
    return true;
  }
}

void service_clock_set_serial () {    //Lee una cadena desde el monitor serie y transforma en datos  
  if (Serial.available()) {           //para el ajuste del reloj
    char set_time[14];
    size_t count = Serial.readBytesUntil('\n', set_time, 14);

    String dt = set_time;

    int i_day =    (dt.substring(0, 2)).toInt();
    int i_month =  (dt.substring(2, 4)).toInt();
    int i_year =   (dt.substring(4, 8)).toInt();
    int i_hour =   (dt.substring(8, 10)).toInt();
    int i_minute = (dt.substring(10, 12)).toInt();


    if (check_valid_data(i_day, i_month, i_year, i_hour, i_minute)) {
      rtc.adjust(DateTime(i_year, i_month, i_day, i_hour, i_minute, 0));  //Inicia el RTC con los datos de ajuste
    } else {
      show_invalid_data();
    }
    process_date();
    process_time();
  } 
}

int read_buttons_updown() {                           //Comprueba si el botĂłn UP o DOWN han sido pulsados
  if (button_pressed (pin_button_clock_up)) {
    return 1;   
  } else if (button_pressed(pin_button_clock_down)) {
    return -1;
  } else {
    return 0;
  }
} 

void service_set_clock_time () {          //Procedimiento de ajuste de fecha y hora por botones
  DateTime dt_utc = rtc.now();
  int time_offset = calc_time_offset(dt_utc);
  DateTime dt_local = dt_utc.unixtime() + time_offset;

  int i_year =   dt_local.year();
  int i_month =  dt_local.month();
  int i_day =    dt_local.day();
  int i_hour =   dt_local.hour();
  int i_minute = dt_local.minute();
  int now_mode = mode_year;
  String s_mode = "YEAR";
  int i_dat = dt_local.year();
  int buttons_updown = 0;

  clear_clock_display();
  show_settings_label(s_mode);
  show_settings_data(i_dat);
  show_set_date_time(i_year, i_month, i_day, i_hour, i_minute);
  
  while (cm_mode != mode_normal) {
    if (button_pressed(pin_button_clock_mode)) {
      switch_clock_mode();
    } else {
      buttons_updown = read_buttons_updown ();
    }

    switch(cm_mode) {
      case mode_year:
        i_year += buttons_updown;        
        i_dat = i_year;
        s_mode = "YEAR";
        break;
      case mode_month:
        i_month += buttons_updown;
        i_month = month_bounds(i_month);         
        i_dat = i_month;
        s_mode = "MONTH";
        break;
      case mode_day: 
        i_day += buttons_updown;  
        i_day = day_bounds(i_year, i_month, i_day);         
        i_dat = i_day;
        s_mode = "DAY";
        break;
      case mode_hour:     
        i_hour = hour_bounds(i_hour += buttons_updown); 
        i_dat = i_hour;
        s_mode = "HOUR";        
        break;
      case mode_minute:       
        i_minute = minute_bounds(i_minute += buttons_updown); 
        i_dat = i_minute;
        s_mode = "MINUTE";
        break;
      case mode_end_of_process:
        show_end_of_process_display ();
        if (buttons_updown != 0) {
          if (buttons_updown == 1) { 
            rtc.adjust(DateTime(i_year, i_month, i_day, i_hour, i_minute, 0));
          }
          cm_mode = mode_normal;
        }
        break;
    }    
    if (now_mode != cm_mode) {
      show_settings_label(s_mode);
      show_settings_data(i_dat);
      now_mode = cm_mode;
    }

    if (buttons_updown != 0) {
      show_settings_data(i_dat);
      show_set_date_time(i_year, i_month, i_day, i_hour, i_minute);
    }
  }
  clear_clock_display();
  process_date();
}

void process_date() {         //Procesa los datos de fecha y los saca a pantalla
  DateTime dt_utc = rtc.now();
  int time_offset = calc_time_offset(dt_utc);
  DateTime dt_local = dt_utc.unixtime() + time_offset; 
  byte col_max = 20;
  byte col_init = 0;
  byte row_date = 0;
  byte row_day_of_the_week = 1;
  String s_month = name_of_month(dt_local.month());
  String s_day_of_the_week = name_of_the_day_of_the_week(dt_local.dayOfTheWeek());
  String s_date = String(dt_local.day());

  s_date.concat(" * ");
  s_date.concat(s_month);
  s_date.concat(" * " );
  s_date.concat(dt_local.year());
 
  lcd.setCursor(col_init, row_date);
  lcd.print("                    ");
  lcd.setCursor(((col_max - s_date.length()) / 2), row_date);
  lcd.print(s_date);

  lcd.setCursor(col_init, row_day_of_the_week);
  lcd.print("                    ");
  lcd.setCursor(((col_max - s_day_of_the_week.length()) / 2), row_day_of_the_week);
  lcd.print(s_day_of_the_week); 
}

void process_time() {       //Procesa los datos de hora y los muestra en pantalla
  DateTime dt_utc = rtc.now();
  int time_offset = calc_time_offset(dt_utc);
  DateTime dt_local = dt_utc.unixtime() + time_offset;
  char buf_local[] = "hh:mm:ss";
  char buf_utc[] = "hh:mm";
  byte col_local = 0;
  byte col_utc = 11;
  byte row_hour = 2;
  
  lcd.setCursor(col_local, row_hour);
  lcd.print(dt_local.toString(buf_local));

  lcd.setCursor(col_utc, row_hour);
  lcd.print("UTC=");
  lcd.print(dt_utc.toString(buf_utc));
}

/*
 * Procedimientos y funciones del conmutador de bandas
 */
 
bands decode_band(float r_band) { //r_band es la lectura de la entrada analĂłgica de bandas  
  if (r_band <= 100.0) {
    return b30;
  } else if (r_band > 228.0 && r_band <= 268.0) {     //raw = 248, 1,212V
    return b6;
  } else if (r_band > 274.0 && r_band <= 314.0) {     //raw = 294, 1,437V
    return b10;
  } else if (r_band > 373.0 && r_band <= 473.0) {     //raw = 423, 2,067V
    return b15;
  } else if (r_band > 481.0 && r_band <= 591.0) {     //raw = 541, 2,644V
    return b20;
  } else if (r_band > 624.0 && r_band <= 724.0) {     //raw = 674, 3,294V
    return b40;
  } else if (r_band > 757.0 && r_band <= 857.0) {     //raw = 897, 3,944V
    return b80;
  } else if (r_band > 886.0) {                        //raw = 936, 4,819V
    return b160;
  } else {
    return b0; 
  }
}

String name_of_band() {
  switch(active_band) {
    case   b0: return "NULL";
    case   b6: return "6m";
    case  b10: return "10m12m";
    case  b15: return "15m17m";
    case  b20: return "20m";
    case  b30: return "30m";
    case  b40: return "40m";
    case  b80: return "80m";
    case b160: return "160m";
  }
}

float read_analog_io (int pin) {    //Lectura (100 lecturas) de una entrada analĂłgica y deviuelve el promedio
  float raw = 0.0;
  for (int i = 1; i <= 100; i++) {
    raw += analogRead(pin);
  }
  return raw / 100.0;
}

void check_active_rig () {    //Detecta si el Icom está encendido
  float raw_power = read_analog_io (power_input); 
  if (raw_power > 400) {
    active_rig = power_on;  
  } else {
    active_rig = power_off;
  }
}

void check_active_band () {   //active_band es una variable global que contiene la banda activa   
  float raw_band = read_analog_io (bands_input);   
  active_band = decode_band (raw_band); 
}

void active_relays_antennas (bool hex, bool ape) {  //Conmuta los relés de antenas 
  digitalWrite(pin_relay_hexbeam, hex);             //hex y ape tienen dos estados HIGH y LOW    
  digitalWrite(pin_relay_aperiodic, ape);
}

void check_active_antenna () {    //Detecta la antena activa y la almacena en la variable global active_antenna
  antennas old_antenna = active_antenna;
  bool relay_hexbeam;
  bool relay_aperiodic;
  
  if (active_band == b6 || active_band == b10 || active_band == b15 || active_band == b20) {
    active_antenna = hexbeam;
    relay_hexbeam = true;
    relay_aperiodic = false;  
  } else if (active_band == b30 || active_band == b40 || active_band == b80 || active_band == b160) {
    active_antenna = aperiodic;
    relay_hexbeam = false;
    relay_aperiodic = true; 
  } else {
    active_antenna = none;
    relay_hexbeam = false;
    relay_aperiodic = false; 
  }
  active_relays_antennas (relay_hexbeam, relay_aperiodic);
}

void switch_antennas_modes () {   //Conmuta secuencialmente los modos (automático y manual) del conmutador
  switch (antenna_mode) {
    case automatic:
      antenna_mode = manual_hexbeam;
      active_antenna = hexbeam;
      active_relays_antennas (HIGH, LOW);
      break;
    case manual_hexbeam:
      antenna_mode = manual_aperiodic;
      active_antenna = aperiodic;
      active_relays_antennas (LOW, HIGH);
      break;
    case manual_aperiodic:
      antenna_mode = automatic;
      check_active_antenna ();
      break;
  }
  
  show_active_antenna ();
  show_active_band ();
}

void show_active_band () {  //Muestra en pantalla la banda activa
  lcd.setCursor(0, 3);
  if (antenna_mode == automatic) {
    lcd.print("BAND=      ");
    lcd.setCursor(5, 3);
    lcd.print(name_of_band());      
  } else {
    lcd.print("MANUAL    ");
  }
   
}

void show_active_antenna () { //Muestra en pantalla la antena activa (o el modo)
  int col_init = 11;
  String ant = "APERIODIC";
  
  if (active_antenna == hexbeam) {
    col_init = 13;
    ant = "HEXBEAM";    
  }
  lcd.setCursor(11, 3);
  lcd.print("         ");
  lcd.setCursor(col_init, 3);
  lcd.print(ant);
}

void show_rig_off (){ 
  lcd.setCursor(0, 3);
  lcd.print("TRANSCEPTOR APAGADO ");
}

void service_rig () { //Procesa el estado del Icom (Âżse ha encendido o apagado?
  power old_status = active_rig;
  check_active_rig ();
  if (old_status != active_rig) {
    if (active_rig == power_on) {
      check_active_band ();
      check_active_antenna ();
      show_active_band ();
      show_active_antenna ();  
    } else {
      show_rig_off ();
    }
  }  
}

void service_bands () { //Procesa la banda (ÂżHa habido canbio de banda?)
  bands old_band = active_band;
  antennas old_antenna = active_antenna;
  check_active_band ();
  if (old_band != active_band) {
    show_active_band ();
    check_active_antenna ();

Serial.print("Hexbeam = ");
Serial.println(digitalRead(pin_relay_hexbeam));

Serial.print("Aperiodic = ");
Serial.println(digitalRead(pin_relay_aperiodic));
    
    if (old_antenna != active_antenna) {
      show_active_antenna ();  
    }
  }
}

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(50);
  rtc.begin();

  lcd.init();
  lcd.backlight();
  lcd.clear();
    
  pinMode(pin_button_clock_up, INPUT_PULLUP);
  pinMode(pin_button_clock_mode, INPUT_PULLUP);
  pinMode(pin_button_clock_down, INPUT_PULLUP);
  pinMode(pin_button_antennas_mode, INPUT_PULLUP);
  pinMode(pin_relay_hexbeam, OUTPUT);
  pinMode(pin_relay_aperiodic, OUTPUT);

  digitalWrite(pin_relay_hexbeam, LOW);
  digitalWrite(pin_relay_aperiodic, LOW);

  check_active_rig ();  
  check_active_band ();
  check_active_antenna ();
  
  if (active_rig == power_on) {
    show_active_band ();
    show_active_antenna ();

Serial.print("Hexbeam = ");
Serial.println(digitalRead(pin_relay_hexbeam));

Serial.print("Aperiodic = ");
Serial.println(digitalRead(pin_relay_aperiodic));
    
  } else {
    active_relays_antennas (LOW, LOW);
      show_rig_off ();
  }
  process_date();
}

void loop() {
  service_rig ();
  if (active_rig == power_on && antenna_mode == automatic) {
    service_bands ();
  }

  if (button_pressed(pin_button_antennas_mode)) {
    switch_antennas_modes ();    
  }
  
  service_clock_set_serial();
  if (button_pressed(pin_button_clock_mode) && cm_mode == mode_normal) {
    cm_mode = mode_year;
    service_set_clock_time();
  }

  if (cm_mode == mode_normal) {
    if (check_next_day()) {
      process_date();
    }
    process_time();
  }
} or paste code here
#define pin_button_clock_mode 15
#define pin_button_clock_up 11
#define pin_button_clock_down 9
#define pin_button_antennas_mode 40 //Esta para modificar porque el botón está en corto
#define pin_relay_hexbeam 44
#define pin_relay_aperiodic 42
#define power_input A5
#define bands_input A1

//#define LANGUAGE_ENGLISH
#define LANGUAGE_SPANISH
//#define LANGUAGE_EUSKERA
//#define LANGUAGE_CATALAN

#ifdef LANGUAGE_SPANISH
  #define week_1 "LUNES"
  #define week_2 "MARTES"
  #define week_3 "MIERCOLES"
  #define week_4 "JUEVES"
  #define week_5 "VIERNES"
  #define week_6 "SABADO"
  #define week_7 "DOMINGO"
  #define month_01 "ENERO"
  #define month_02 "FEBRERO"
  #define month_03 "MARZO"
  #define month_04 "ABRIL"
  #define month_05 "MAYO"
  #define month_06 "JUNIO"
  #define month_07 "JULIO"
  #define month_08 "AGOSTO"
  #define month_09 "SEPTIEMBRE"
  #define month_10 "OCTUBRE"
  #define month_11 "NOVIEMBRE"
  #define month_12 "DICIEMBRE"
#endif //LANGUAGE_SPANISH

#ifdef LANGUAGE_ENGLISH
  #define week_1 "MONDAY"
  #define week_2 "TUESDAY"
  #define week_3 "WEDNESDAY"
  #define week_4 "THURSDAY"
  #define week_5 "FRIDAY"
  #define week_6 "SATURDAY"
  #define week_7 "SUNDAY"
  #define month_01 "JANUARY"
  #define month_02 "FEBRUARY"
  #define month_03 "MARS"
  #define month_04 "APRIL"
  #define month_05 "MAY"
  #define month_06 "JUNE"
  #define month_07 "JULY"
  #define month_08 "AUGUST"
  #define month_09 "SEPTEMBER"
  #define month_10 "OCTOBER"
  #define month_11 "NOVEMBER"
  #define month_12 "DECEMBER"
#endif //LANGUAGE_ENGLISH

#ifdef LANGUAGE_EUSKERA
  #define week_1 "ASTELENA"
  #define week_2 "ASTEARTEA"
  #define week_3 "ASTEASKENA"
  #define week_4 "OSTEGUNA"
  #define week_5 "OSTIRALA"
  #define week_6 "LARUNBATA"
  #define week_7 "IGANDEA"
  #define month_01 "URTARRILA"
  #define month_02 "OTSAILA"
  #define month_03 "MARTXOA"
  #define month_04 "APIRILA"
  #define month_05 "MAIATZA"
  #define month_06 "EKAINA"
  #define month_07 "UTZAILA"
  #define month_08 "ABUZTUA"
  #define month_09 "IRAILA"
  #define month_10 "URRIA"
  #define month_11 "AZAROA"
  #define month_12 "ABENDUA"
#endif //LANGUAGE_EUSKERA

#ifdef LANGUAGE_CATALAN
  #define week_1 "DILLUNS"
  #define week_2 "DIMARTS"
  #define week_3 "DIMECRES"
  #define week_4 "DIJOUS"
  #define week_5 "DIVENDRES"
  #define week_6 "DISSABTE"
  #define week_7 "DIUMENGE"
  #define month_01 "GENER"
  #define month_02 "FEBRER"
  #define month_03 "MARÇ"
  #define month_04 "ABRIL"
  #define month_05 "MAIG"
  #define month_06 "JUNY"
  #define month_07 "JULIOL"
  #define month_08 "AGOST"
  #define month_09 "SETEMBRE"
  #define month_10 "OCTUBRE"
  #define month_11 "NOVEMBRE"
  #define month_12 "DESEMBRE"
#endif //LANGUAGE_CATALAN

enum power {
  power_off, 
  power_on};
  
enum bands {
  b0, 
  b6, 
  b10, 
  b15, 
  b20, 
  b30, 
  b40, 
  b80, 
  b160};

enum antennas_modes {
  automatic, 
  manual_hexbeam, 
  manual_aperiodic};
  
enum antennas {
  none, 
  hexbeam, 
  aperiodic};
  
power active_rig;
bands active_band;
antennas active_antenna;
antennas_modes antenna_mode = automatic;

enum month_name {
  january = 1, 
  february, 
  march, 
  april, 
  may, 
  june, 
  july, 
  august, 
  september, 
  october, 
  november, 
  december};
  
enum dow_name {
  sunday, 
  monday, 
  tuesday, 
  wednesday, 
  thusday, 
  friday, 
  saturday};
  
enum clock_mode {
  mode_normal, 
  mode_year, 
  mode_month, 
  mode_day, 
  mode_hour, 
  mode_minute, 
  mode_end_of_process};

month_name mn_month;
dow_name dn_dow;
clock_mode cm_mode = mode_normal;

LiquidCrystal_I2C lcd(0x27, 20, 4);
RTC_DS3231 rtc; or paste code here

Sorry but how does this relate to the code in your first post?

Sorry, I have no experience posting code on the forum. My code has two files, band_switch_watch.ino and defines.h

In the second file, defines.h, there are the lines described that assign the IOs (D42 and D44) that control the relays.

The code works fine. The IO 42 or 44 go to the logical state of HIGH when it corresponds, but the voltage is not enough to act on the UDN2981A driver. I cannot explain what is happening and I have tried several MEGA cards. This circuit has worked with an Arduino NANO. I need guidance to consult some text on managing relays with MEGA.

I try the IO state with two lines:

Serial.println(digitalRead(pin_relay_hexbeam));
Serial.println(digitalRead(pin_relay_aperiodic));

The response has been 1 or 0 when each relay should have been activated, but the voltage measured at each IO is always 0.

You are not alone. The forum software changed radically last Monday so no one has much experience of posting code.

The thing is that what you are doing with the read of an output pin is simply looking at the internal registers.

What we need to see is a detailed diagram of the connection between your Mega and the relay driver. Is it a board or a circuit?

What voltage do you get on these pins with nothing connected to them?
This sort of thing can happen if you don’t define these pins as outputs, or something redefines them a inputs before you use them. That might not be a specific pin mode call but could be done by writing directly to the registers, or enabling pull ups. It could also be a result of burned out pins. Maybe try another pair?

Hi,
What pins do you have the relays connected to in your circuit?
What pins do you configure as the relay pins in your code?

42 or 44 or 32 or 34 ?

Tom… :smiley: :+1: :coffee: :australia:

This is the schema ofthe outputs to UDN 2181, the drivers the relays at 12V.

Thanks, Arsenio

I had a quick look into datasheet of UDN2981. The driver is non-inverting, i.e. it requires high-level to create high-level at its output. It is acting as high-side switch. So far, the circuit seems ok.

What I don’t know are the capabilities of the MEGA 2560 to source, i.e. supply, output current. Usually I/Os can sink more current than they can provide. Nevertheless, the UDN2981 requires about 0.4mA at 5V, which I would not expect to overload the I/O of the MEGA 2560. Nevertheless, double-check… otherwise the 2 Volts are a result of an overloaded I/O.

That circuit is wrong. It shows Pin 1 trying to control a relay on pin 18 and pin 2 controlling a relay on pin 17. This is the pinout you should be using.

Many thanks sebastian, now I work on an independent circuit and will test with a NANO.

Thanks grumpy_Mike, but I use a UDN2981 that has 18 pins for drive 8 actuators, not 20. It’s different than the A2982SLW for 9 actuators that you propose.

Hi,
2981 pinouts;

Tom… :grinning: :+1: :coffee: :australia:

Which is to say, no difference other than two extra pins. :roll_eyes:

The Mega 2560 and ATmegaxx8 devices are symmetrical.

I agree TomGeorge. I have not had time to test a new circuit with NANO yet.

The project is published on my blog and yes, it has worked. The current one with IO 42 and 44 is the same as the previous one, there are the diagrams and the point-to-point electrical circuit.

Any way the watch work well. The code of watch is uploaded to GitHub.

dual watch and antenna switch

Ah, ok, good to know, and well, makes sense. Thanks.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.