I think I let the magic smoke out...Can someone confirm?

I had been working on a project using a 12v supply through the Vin Pin. There were a few times (less than 5 that I can recall) that I plugged my USB in while powering the mega with the Vin. Now when I power up the mega the sketch I’m running tells me that its reading over 3 volts. When in reality there is only .8v at the analog input. Prior to using the USB and the 12v at the same time that the analog read and calculations everything seemed to be working well.

Have I permanently damaged my mega? Is there anything that I can do to double check for damage?

Thanks,

Loren
below is the sketch I had been running:

#include<UTFT.h>
#include<UTouch.h>
#include "Menus.h"


extern uint8_t SmallFont[];
//UTFT myGLCD(ITDB32S, 38,39,40,41);   // Remember to change the model parameter to suit your display module!
//UTouch myTouch(6,5,4,3,2);


//Sketch Variables

int mnu;
int x,y;
int voltagepin = 0;
int involt = 0;
int currpin = 1;
int inamp = 0;
int dec, inte;

//average


//millis

unsigned long time;
unsigned long currTime=0;

Menus menus;


//pulse in

/*int pulsepin = 8;
 unsigned long duration;*/



//fan stuff:

//Varibles used for calculations
int NbTopsFan =0; 
int Calc;

//The pin location of the sensor
int hallsensor = 8;


typedef struct{                  //Defines the structure for multiple fans and their dividers
  char fantype;
  unsigned int fandiv;
}
fanspec;

//Definitions of the fans
fanspec fanspace[3]={
  {
    0,1            }
  ,{
    1,2            }
  ,{
    2,8            }
};

char fan = 1;   //This is the varible used to select the fan and it's divider, set 1 for unipole hall effect sensor 
//and 2 for bipole hall effect sensor







void setup(){

  Serial.begin(9600);
  analogReference(INTERNAL1V1);

  menus.initScrn();
  menus.homeScrn();

  //average





  pinMode(hallsensor, INPUT); 
  attachInterrupt(0, rpm, RISING); 
  sei();	//Enables interrupts

  //pinMode(pulsepin, INPUT); 



}


void loop(){
  menus.touched();


  involt=analogRead(voltagepin);
  delay(10);
  involt=analogRead(voltagepin);
  delay(10);
  inamp =analogRead(currpin);
  delay(10);
  inamp =analogRead(currpin);


  float Vcc = readVcc()/1000.0;
  float Voltage = ((involt / 1023.0)*Vcc)/.0584;
  float Ref = (involt /1023.0)*Vcc;
  String refVal = dtostrf(Ref,5,4,"stuff");
  //String refVal = String(Ref);
  menus.refval(refVal);

  split(Voltage);
  menus.setvolts(inte, dec);

  float Amperage = ((inamp / 1023.0) * Vcc);
  split(Amperage);
  menus.setamps(inte, dec);

  // delay one second without delaying
  time = millis();
  unsigned long diff;
  diff = time - currTime;
  if (diff>1000){
    cli();	//Disable interrupts
    Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv); //Times NbTopsFan (which is apprioxiamately the fequency the fan is spinning at) by 60 seconds before dividing by the fan's divider

    NbTopsFan = 0;	//Set NbTops to 0 ready for calculations
    sei();	//Enables interrupts


    //duration = pulseIn(pulsepin, HIGH);
    String fanspeed = String(Calc);
    fanspeed+=" rpm";
    Serial.println("Speed:  " + fanspeed);
    menus.rptfan(fanspeed);
    currTime = time;
  }










}

long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif  

  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both

  long result = (high<<8) | low;

  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}


void split(float volts){
  //Serial.println(volts);
  int IntegerPart = (int)(volts);
  inte =IntegerPart;
  //Serial.println(IntegerPart);
  int DecimalPart = 100 * (volts - IntegerPart);
  dec = DecimalPart;
  //Serial.println( DecimalPart);

}



///fan:

void rpm ()      //This is the function that the interupt calls 
{ 
  NbTopsFan++; 
}

When you have an official Arduino Mega 2560, you can connect power to usb, barrel jack and Vin. You can connect one or two or all of them and disconnect and reconnect while running.

Something tells me there is something fishy about your sketch. When you set the analogReference to 1.1V, you should never be able to read 3V at an analog input pin. When you read the Vcc, you don't seem to reset the mux.

I have used the ReadVcc() on a few different Arduino boards, and the Mega board was very hard to return to normal accurate reading. I had to set the mux normal, read a dummy analog value, delay 20ms, read another dummy analog value. In the end I was still not able to return to accurate reading after that, so I decided to use an external voltage divider to read the 5V of the Mega board.

Peter,

Thanks for the reply. I'm actually trying to read this: https://www.sparkfun.com/products/9028 This is a voltage divider, right?

Do you have any recommendations about how to read the sensor?

Thanks

No, a voltage divider is just two resistors.
Suppose you have a reference of 1.1V, so the measured voltage should be lowered into that range.
When you use a voltage divider with 4k7 and 1k (4k7 to 5V, 1k to GND, analog input connect to the middle) you divide the voltage with 1/(1+4.7).
When you read 0.877V, it is 5.0V at the other end of the 4k7.
http://teaching.ericforman.com/voltage-divider-circuit/

You can still try to make that sketch working. Even with readVcc(). I’m afraid that with the 2 resistors, you run into new troubles.
At this moment I prefer to get something working, and accuracy is something for later.

First of all, what kind of voltage do you want to read with the ‘voltagepin’ ? Are there peaks that could damage the Arduino ?
Select the reference you need, 1.1V 2.56V or DEFAULT 5V.
http://arduino.cc/en/Reference/AnalogReference
Stick with that reference during the sketch, and use that in the calculations.
When you select the internal 1.1V, don’t do the calculation with the 5V of readVcc. That is of no use.

At the end of readVcc(), try to repair the analog settings.

long readVcc() {
   ...

  // Try to set the mux normal
  analogReference(...);       // set the the reference voltage that you choose
  analogRead(0);             // set mux and dummy read
  delay(20);                 // wait for voltages to become stable
  analogRead(0);        // another dummy read.

  return result; // Vcc in millivolts
}

Peter_n: No, a voltage divider is just two resistors.

Got it.

I did a little more reading on the atto pilot sensor last night.

Peter_n: You can still try to make that sketch working. Even with readVcc(). I'm afraid that with the 2 resistors, you run into new troubles. At this moment I prefer to get something working, and accuracy is something for later.

Agreed

Peter_n: First of all, what kind of voltage do you want to read with the 'voltagepin' ?

From the product sheet:

Voltage sense is accomplished by scaling to 3.3V ADC range by a precision resistor divider.

at 50v the sensor will output 3.3v I don't think I'll ever supply it more than 24v and for testing purposes I'm feeding the sensor 12v which yeilds .8v at the output. I would guess that switching the reference to 2.56V might not be a bad idea.

Peter_n: Are there peaks that could damage the Arduino ?

Not that I have seen.

Peter_n: When you select the internal 1.1V, don't do the calculation with the 5V of readVcc. That is of no use.

Where do you see this happening? This is where I'm confused about where I've inadvertently started to use 5v instead of 1.1.

Peter_n: At the end of readVcc(), try to repair the analog settings.

long readVcc() {
   ...

  // Try to set the mux normal   analogReference(...);       // set the the reference voltage that you choose   analogRead(0);             // set mux and dummy read   delay(20);                 // wait for voltages to become stable   analogRead(0);        // another dummy read.

  return result; // Vcc in millivolts }

I've added this to my sketch in the readVcc function.

Let's focus on this section:

  involt=analogRead(voltagepin);
  delay(10);
  involt=analogRead(voltagepin);
  delay(10);
  inamp =analogRead(currpin);
  delay(10);
  inamp =analogRead(currpin);


  float Vcc = readVcc()/1000.0;
  float Voltage = ((involt / 1023.0)*Vcc)/.0584;

I prefer to use real units. First calculate the voltage at the pin, after that calculate the voltage from a voltage divider. The number ".0584" doesn't have a meaning. You need to explain that. When you calculate the voltage at a pin first, it is easy to show that in the serial monitor and to measure it with a multimeter. Don't worry about more code lines, or using a lot more variables, the compiler will take care of that and optimize it.

  // read the raw ADC value with an integer
  involt=analogRead(voltagepin);
  inamp =analogRead(currpin);

  // calculate the voltage at the Arduino pin.
  // Assuming that the Arduino reference voltage is 1.1V.
  float voltage_involt = (float) involt / 1023.0 * 1.1;
  float voltage_inamp = (float) inamp / 1023.0 * 1.1;

  // calculate the real voltage and current
  // Please explain here what the value 0.0584 is.
  float Voltage = voltage_involt / 0.0584;
  // Please explain here how to calculate the amperes.
  float Amperage = voltage_inamp;

This morning I did simplify the code a little I took out the .0584 to try and read the raw voltage. The .0584 previously showed me the voltage at the being fed into the sensor.

I'll try the code you posted above when I get home later today.

Ok… Progress!

The following code works:

  float voltage_involt = (float) involt / 1023.0 * 1.1;
  float sensor_in = voltage_involt/.0648;
  float voltage_inamp = (float) inamp / 1023.0 * 1.1;
  String refVal = dtostrf(sensor_in,5,4,"stuff");
  menus.refval(refVal);

  split(sensor_in);
  menus.setvolts(inte, dec);

voltage_involt measures the voltage going into arduino
Sensor_in is the voltage that is calculated to reflect the voltage being fed to the sensor. The supply outputs 12.5v. The sensor is sending .81v. So I divided 12.5 by .81 and then divided 1 by the answer to get .0648.

Peter, was this what you meant or were you suggesting to accomplish this another way? My thought was to work on getting the voltage readings sorted out and then using the same sort of procedure to measure the current.

Thoughts?

You should be able to guess my thoughts..... add comments 8)

I prefer code that shows what it is doing, and I like to split a sketch into seperate functional blocks. A 'block' can be a function (but it doesn't have to be), it makes also testing easier. A good sketch shows what it is doing at a glance.

In your sketch, collecting data and showing it to a display are two seperate things. Only a simple empty line between them will improve the sketch. You can collect all the data and after that display it. Or you can do the voltage first and the current after that. Either way with some comment for each block, it will be easier to understand.

As an example, I added 3 new lines between your code:

  ...
  float voltage_inamp = (float) inamp / 1023.0 * 1.1;

  // Now that all measurements are done,
  // show them on the display
  String refVal = dtostrf(sensor_in,5,4,"stuff");
  ...

I don't know how you measure the current, but perhaps you have to do some calculations in the same way. So yes, you can do the same thing for the current.