About Multi sketches

Hi,
I am merge few sketches into a multi-sketch with few tabs, questions here need help please:

  1. what function should not put into class, such as ISR ?

  2. the project designed with Arduino UNO, there are not enough pins for added items, replaced by MEGA2560, seems the ADC totally different? how to modify this? If put some functions at main sketch, how make it relative to its original sketch?

  3. use NANO may be better?

  4. There are 2 internal clamping diodes on the I/O pins in Arduion, does MEGA2560 has it?

Thanks
Adam

#include <LiquidCrystal.h>   // include Arduino LCD library
// LCD module connections (RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

// define autoranging channel pins
#define CH0  2
#define CH1  3
#define CH2  4
#define CH3  5

const uint16_t Time_Out = 50000,  // time out in microseconds
               Periods  = 10;     // number of periods of measurement (for AC voltage only)

// variables
byte ch_number;
const uint16_t res_table[4] = {2444, 244, 94, 47},  // voltage divider resistances in tenths kOhms
                              total_res = 22444;                   // total resistance in tenths kOhms
uint16_t current_res;
volatile byte per;

void setup(void)
{
  pinMode(CH0, OUTPUT);
  pinMode(CH1, OUTPUT);
  pinMode(CH2, OUTPUT);
  pinMode(CH3, OUTPUT);

  lcd.begin(16, 2);     // set up the LCD's number of columns and rows
  lcd.setCursor(1, 0);
  lcd.print("Voltage:");
  
  ch_number = 0;
  ch_select(ch_number);

  // ADC and analog comparator configuration
  ADMUX  = 0x03;
  ADCSRA = 0x87;
  ADCSRB = (0 << ACME);  // select AIN1 as comparator negative input
  ACSR   = 0x13;         // turn on analog comparator

}

// analog comparator ISR
ISR (ANALOG_COMP_vect)
{
  byte count = 0;
  for (byte i = 0; i < 50; i++) {
    if ( ACSR & 0x20 )
      count++;
  }

  if (count > 48)
    per++;
}

// main loop
void loop()
{
  bool dc_flag = 0; // DC voltage flag bit
  int32_t sum = 0;  // sum of all readings
  uint16_t n = 0;   // number of readings (samples)

  ACSR = (1 << ACI);   // clear analog comparator interrupt flag
  ACSR = (1 << ACIE);  // enable analog comparator interrupt

  uint32_t current_m = micros();  // save current millis
  byte current_per = per;         // save current period number
  while ( (current_per == per) && (micros() - current_m < Time_Out) ) ;

  if ( micros() - current_m >= Time_Out ) { // if there's time out event ==> voltage signal is DC
    dc_flag = 1;
    for (byte i = 0; i < 200; i++) {
      ADCSRA |= 1 << ADSC;   // start conversion
      while (ADCSRA & 0x40); // wait for conversion complete
      int16_t an = (int16_t)(ADCL | (uint16_t)ADCH << 8) - 511;
      sum += an;
      n++;         // increment number of readings
      delay(1);
    }
  }

  else {   // here, voltage signal is AC
    current_m = micros();  // save current millis()
    per = 0;
    while ( (per < Periods) && (micros() - current_m < (uint32_t)Time_Out * Periods) ) {
      ADCSRA |= 1 << ADSC;   // start conversion
      while (ADCSRA & 0x40); // wait for conversion complete
      int32_t an = (int16_t)(ADCL | (uint16_t)ADCH << 8) - 511;
      sum += sq(an);  // sq: square
      n++;            // increment number of readings
    }
  }

  ACSR = (0 << ACIE);  // disable analog comparator interrupt
  uint32_t total_time = micros() - current_m;  // used to claculate frequency

  // voltage calculation
  float v;
  if (dc_flag)  // if voltage signal is DC
    v = (4 * sum) / n; // calculate Arduino analog channel DC voltage in milli-Volts

  else  // here voltage signal is AC
    v = 4 * sqrt(sum / n); // calculate Arduino analog channel RMS voltage in milli-Volts

  // claculate actual (input) voltage in milli-Volts (apply voltage divider equation)
  v = v * (float)total_res / current_res;
  v /= 1000;  // get voltage in Volts

  uint16_t v_abs = abs(int16_t(v));
  if ( (v_abs >= 10 && ch_number == 0) || (v_abs >= 100 && ch_number == 1) || (v_abs >= 250 && ch_number == 2) ) {
    ch_number++;
    ch_select(ch_number);
    delay(10);
    return;
  }

  if ( (v_abs < 220 && ch_number == 3) || (v_abs < 80 && ch_number == 2) || (v_abs < 8 && ch_number == 1) ) {
    ch_number--;
    ch_select(ch_number);
    delay(10);
    return;
  }

  char _buffer[8];
  lcd.setCursor(0, 1);
  if ( v < 0)
    lcd.print('-');
  else
    lcd.print(' ');
  if (v_abs < 10)
    sprintf( _buffer, "%01u.%02u", v_abs, abs((int16_t)(v * 100)) % 100 );
  else if ( v_abs < 100)
    sprintf( _buffer, "%02u.%01u", v_abs, abs((int16_t)(v * 10)) % 10 );
  else
    sprintf( _buffer, "%03u ", v_abs );

  lcd.print(_buffer);
  if (dc_flag)
    lcd.print("VDC        ");
  else {
    lcd.print("VAC ");
    // calculate signal frequency in Hz
    uint32_t period_time = total_time / Periods;
    float freq = 1000000.0 / period_time;
    sprintf( _buffer, "%02u.%02uHz", (uint16_t)freq % 100, (uint16_t)(freq * 100) % 100 );
    lcd.print(_buffer);
  }

  delay(500);    // wait half a second

}

void ch_select(byte n) {
  switch (n) {
    case 0:
      digitalWrite(CH0, HIGH);
      digitalWrite(CH1, LOW);
      digitalWrite(CH2, LOW);
      digitalWrite(CH3, LOW);
      break;
    case 1:
      digitalWrite(CH0, LOW);
      digitalWrite(CH1, HIGH);
      digitalWrite(CH2, LOW);
      digitalWrite(CH3, LOW);
      break;
    case 2:
      digitalWrite(CH0, LOW);
      digitalWrite(CH1, LOW);
      digitalWrite(CH2, HIGH);
      digitalWrite(CH3, LOW);
      break;
    case 3:
      digitalWrite(CH0, LOW);
      digitalWrite(CH1, LOW);
      digitalWrite(CH2, LOW);
      digitalWrite(CH3, HIGH);
  }
  current_res = res_table[n];
}

See if this helps and answers some of your questions.

  1. No functions should be put into an ISR, it should be short and fast as possible.
  2. You can get 4 pins back by using the I2C module with the display. There are also I/O expanders that will operate on the I2C bus. This may be easier then switching to the MEGA although it is code compatible with a lot more memory. The mega has more bits in the A/D. just shift it right by 2 rolling off the additional bits.
  3. The Nano is the same chip with the two additional A/D pined out.
  4. Almost all CMOS logic devices have 2 internal clamping diodes on the I/O pins, it is there to protect the device.
1 Like

Adding - the input protection diodes are not supposed to be used in any circuit that would routinely put current through them. It's only a protection scheme. If you need to clamp, you should clamp with external Schottky diodes (and limit the current so it doesn't get pumped into the power supply).

1 Like

The Atmel 2560 has 10 bit A/D resolution, just like the 328.

1 Like

Thanks.

  1. Sorry of my English, I mean can I put ISR into a class or not? if put ISR which was in a class into main sketch, how to keep its relation with its original class?
  2. How to modify the code above if use a MEGA2560 replace the Arduino UNO?