PDA

Επιστροφή στο Forum : Arduino:Πάλι μη-γραμμικότητα, κάνω κάτι λάθος?



selectronic
30-03-17, 08:27
Καλημέρα,

Δοκιμάζοντας τον έτοιμο κώδικα που βρήκα για να έχω λίγο καλύτερη ανάλυση στην μέτρηση τάσης με AnalogRead, διαπίστωσα ότι δουλεύει μεν αλλά το έως τώρα μικρό σφάλμα μέτρησης λόγο μη-γραμμικότητας στην σχέση τιμής ADC και πραγματικής τάσης, τώρα είναι πολύ μεγαλύτερο και αναιρεί όποια οφέλη προσφέρει η ψευδό-12bit ανάλυση...

Aυτό που έχω δει εγώ τουλάχιστον είναι ότι η καμπύλη των τιμών που δίνει ο ADC σε σχέση με την πραγματική τάση δεν είναι γραμμική, έχει μία ελαφριά καμπύλη. Συγκεκριμένα και με τους 3 Nano που έχω πάντα παίρνω χαμηλότερη τιμή από την πραγματική όταν η τάση είναι κάτω από τα περίπου 200mV και μεγαλύτερη τιμή από την πραγματική από εκεί και πάνω. Ο τρόπος που μετράω είναι να χρησιμοποιώ την εσωτερική Vref των περίπου 1.1V που αλλάζει από τσιπ σε τσιπ (στα δικά μου 1.072 με 1.084V) αλλά είναι αρκετά σταθερή στις αλλαγές θερμοκρασίας κτλ. Εκτός λοιπόν από το να μετράω και να χρησιμοποιώ την "σωστή" Vref στον κώδικα, εμπειρικά κατέληξα να βάζω και άλλη μια παράμετρο στοω υπολογισμό της τάσης, που βοηθάει να ισιώσει κάπως αυτή η καμπύλη: από δοκιμές βρήκα ότι (AnalogRead + 2.0περίπου ) / 1024.0 * Vref λειτουργεί αρκετά καλά, με 1-2mV λιγότερα στις μικρότερες μετρήσεις και άλλα +1-2mV για το μέγιστο του ~1.1V

Είπα λοιπόν να δοκιμάσω την βιβλιοθήκη NewAnalogRead του eRCaGuy (http://forum.arduino.cc/index.php?topic=240509.0) και όντος είδα μία μικρή βελτίωση στην ανάλυση, αλλά μαζί χειροτερεύει και το πρόβλημα της μη-γραμμικότητας: στα 35mV μετράει -5mV πιο κάτω και στα 736mV μετράει +41mV περισσότερα!
Για την ιστορία η διαφορά στην ανάλυση που είδα είναι η παρακάτω: για πραγματική τάση μεταξύ 100 και 101mV στα 10bit είχα μόνο ένα βήμα στην μέτρηση με AnalogRead, τώρα έχω τουλάχιστον 3!!! Μέχρι εκεί όμως, στα 12bit που το δοκίμασα δουλεύει αλλά με 14bit δεν υπάρχει πρακτικά διαφορά αφού δεν δουλεύω στην NASA να έχω εξοπλισμό που να μετράει ένα-ένα τα μικροβόλτ...

Βοηθήστε με βρε παιδιά, τι κάνω λάθος ???

Ο απλός κώδικας που χρησιμοποιώ και μετράει στα +-2mV περίπου:



#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 4, 6, 7, 8, 9);
float Vref11 = 1.082;
float CalibV = 2.0;
int Read1 = A0;

void setup()
{
analogReference (INTERNAL);
lcd.begin(20, 2);
}

void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);


// κλόπη-Paste μέθοδος για απόρριψη "κουλών" τιμών μέτρησης που μπορεί να προέρχονται από θόρυβο κτλ. Κάνει δουλειά!

int rawADC0 = analogRead (Read1);
int rawADC1 = analogRead (Read1);
int rawADC2 = analogRead (Read1);
int rawADC3 = analogRead (Read1);
int rawADC4 = analogRead (Read1);
int rawADC5 = analogRead (Read1);
int rawADC6 = analogRead (Read1);
int rawADC7 = analogRead (Read1);
int rawADC8 = analogRead (Read1);
int rawADC9 = analogRead (Read1);
int rawADC10 = analogRead (Read1);
int rawADC11 = analogRead (Read1);
int rawADC12 = analogRead (Read1);
int rawADC13 = analogRead (Read1);
int rawADC14 = analogRead (Read1);
int rawADC15 = analogRead (Read1);
int rawADC16 = analogRead (Read1);
int rawADC17 = analogRead (Read1);
int rawADC18 = analogRead (Read1);
int rawADC19 = analogRead (Read1);

int average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;

float OnePercentADC = (float) average / 1000;
float percentADC = OnePercentADC * 6;

float average2 = 0;
int count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {average2 = average2 + rawADC0; count++;}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {average2 = average2 + rawADC1; count++;}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {average2 = average2 + rawADC2; count++;}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {average2 = average2 + rawADC3; count++;}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {average2 = average2 + rawADC4; count++;}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {average2 = average2 + rawADC5; count++;}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {average2 = average2 + rawADC6; count++;}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {average2 = average2 + rawADC7; count++;}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {average2 = average2 + rawADC8; count++;}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {average2 = average2 + rawADC9; count++;}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {average2 = average2 + rawADC10; count++;}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {average2 = average2 + rawADC11; count++;}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {average2 = average2 + rawADC12; count++;}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {average2 = average2 + rawADC13; count++;}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {average2 = average2 + rawADC14; count++;}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {average2 = average2 + rawADC15; count++;}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {average2 = average2 + rawADC16; count++;}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {average2 = average2 + rawADC17; count++;}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {average2 = average2 + rawADC18; count++;}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {average2 = average2 + rawADC19; count++;}
average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * Vref11;

lcd.setCursor(5, 0);
lcd.print(voltage,3);lcd.print("V");

lcd.setCursor(12, 0);
lcd.print(" ");
lcd.setCursor(12, 0);
lcd.print(average);

lcd.setCursor(17, 0);
lcd.print(" ");
lcd.setCursor(17, 0);
lcd.print(count);
}


Βίντεο (χείριστης ποιότητας :( ) που δείχνει ότι μετράει "OK":
Πάνω γραμμή είναι Timer, Τάση , ADC , count. Η κάτω γραμμή είναι άλλη μία τάση που μετράω, δεν αλλάζει. Το κύκλωμα είναι μόνο η LCD και ένας διαιρέτης με δύο pot που βγάζουν τις τάσεις που μετράω.


https://youtu.be/fnpvHt8Mwd0

Κώδικας από το Παράδειγμα (basic_demo) της βιβλιοθήκης NewAnalogRead, που μετράει +40mV στα 745mV:
*το παράδειγμα είναι σε 14bit αλλά δεν έχει νόημα όπως είπα, οι τιμές που πήρα και έφτιαξα τα γραφήματα πιο κάτω είναι όπως παρακάτω, στα 12bit


/*
NewAnalogRead_basic_demo.ino
-This is a demo of this library: eRCaGuy_NewAnalogRead, which replaces eRCaGuy_analogReadXXbit
-Written for Library Version: 2.1
Library webpage: http://electricrcaircraftguy.blogspot.com/2014/05/using-arduino-unos-built-in-16-bit-adc.html
-This is a library to utilize oversampling, by the 10-bit Arduino ADC (Analog to Digital Converter), in
order to obtain much higher resolutions. You may command any resolution from 10-bit to 21-bit, though oversampling has
its limiations and you may not see improvements beyond ~16-bit commands. There are a lot of variables, so you will
just have to play around and find out. The tradeoff in commanded resolution is speed. The higher the commanded resolution,
the longer it takes to get an ADC reading. Each new bit of resolution decreases the max read speed by a factor of 4. See the
top of the .h file for much more info.
-Additionally, this library provides automatic averaging of multiple readings, at your desired
resolution of course, in order to smooth incoming data.
-For the theory behind oversampling, see AVR121 Application Note: http://www.atmel.com/images/doc8003.pdf
--esp. take a look at Table 3-1, Resolution Options, on pg. 8

By Gabriel Staples
http://electricrcaircraftguy.blogspot.com/
-My contact info is available by clicking the "Contact Me" tab at the top of my blog.
Written: 17 Feb. 2015
Last Updated: 17 Feb. 2015
*/

/*
================================================== =================================================
LICENSE & DISCLAIMER
Copyright (C) 2014-2015 Gabriel Staples. All right reserved.

This file is part of eRCaGuy_NewAnalogRead.

I AM WILLING TO DUAL-LICENSE THIS SOFTWARE. HOWEVER, UNLESS YOU HAVE PAID FOR AND RECEIVED A RECEIPT
FOR AN ALTERNATE LICENSE AGREEMENT, FROM ME, THE COPYRIGHT OWNER, THIS SOFTWARE IS LICENSED AS FOLLOWS:

------------------------------------------------------------------------------------------------
License: GNU General Public License Version 3 (GPLv3) or later - https://www.gnu.org/licenses/gpl.html
------------------------------------------------------------------------------------------------

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/
================================================== =================================================
*/

/*
Circuit:
We need to read an analog voltage on A0, so place a pot with the outer legs going to 5V and GND, respectively, and the wiper (middle leg) going to A0
-make sure to set your Serial Monitor to 115200 baud rate
*/

//include the library
#include <eRCaGuy_NewAnalogRead.h>

//Global variables
byte pin = A0;
byte bitsOfResolution = 12; //commanded oversampled resolution
unsigned long numSamplesToAvg = 1; //number of samples AT THE OVERSAMPLED RESOLUTION that you want to take and average
ADC_prescaler_t ADCSpeed = ADC_FAST;
/*Speed options to store into ADCSpeed are as follows:
ADC_PRESCALER_128_CLOCK_125KHZ
ADC_DEFAULT (same as above)
ADC_SLOW (same as above)
ADC_PRESCALER_64_CLOCK_250KHZ
ADC_PRESCALER_32_CLOCK_500KHZ
ADC_PRESCALER_16_CLOCK_1MHZ
ADC_FAST (same as above)
CAUTION_ADC_PRESCALER_8_CLOCK_2MHZ
CAUTION_ADC_PRESCALER_4_CLOCK_4MHZ
CAUTION_ADC_PRESCALER_2_CLOCK_8MHZ
NB: if you change the ADC clock speed, it doesn't just affect this library, it also affects the
ADC sample rate when calling the standard core Arduino analogRead() function.
*/

void setup()
{
Serial.begin(115200);
Serial.println(F("Oversampling example, commanding 10-bit to 21-bit resolution using a 10-bit ADC on an Arduino"));
Serial.println(F("Basic demo"));
Serial.println(""); //add a line space

//print defaults
Serial.println(F("Default adc values:"));
printValues();

//Configure the adc how you want it
adc.setADCSpeed(ADCSpeed);
adc.setBitsOfResolution(bitsOfResolution);
adc.setNumSamplesToAvg(numSamplesToAvg);

//Verify your changes
Serial.println(F("New adc values:"));
printValues();
}

void loop()
{
//local variables
unsigned long analogReading;

//take a reading on the analog pin
//note: this is an overloaded function, so there are 4 ways to do it!
//Method 1: just take a reading, providing the pin number only; the library will use other values as necessary
// that you already set with the "adc.set..." functions above
analogReading = adc.newAnalogRead(pin); //get the avg. of [num_samples] [bits_of_resolution]-bit readings
//Method 2: update what the library has stored for bitsOfResolution, AND take a new reading
// analogReading = adc.newAnalogRead(pin,bitsOfResolution); //UNCOMMENT TO USE
//Method 3: update what the library has stored for bitsOfResolution and numSamplesToAvg, AND take a new reading
// analogReading = adc.newAnalogRead(pin,bitsOfResolution,numSamplesT oAvg); //UNCOMMENT TO USE
//Method 4: update what the library has stored for bitsOfResolution and numSamplesToAvg, then set the ADCSpeed, AND take a new reading
// analogReading = adc.newAnalogRead(pin,bitsOfResolution,numSamplesT oAvg,ADCSpeed); //UNCOMMENT TO USE

//output results
Serial.print("analogReading = "); Serial.print(analogReading);
Serial.print(", Voltage (V) = "); Serial.println(5.0*analogReading/adc.getMaxPossibleReading(),5); //display up to 5 digits of precision

//wait a bit before taking another reading, so as to not overburden the serial port
delay(50);
}

//print adc settings
void printValues()
{
Serial.print(F("bitsOfResolution = ")); Serial.println(adc.getBitsOfResolution());
Serial.print(F("MaxPossibleReading at this res = ")); Serial.println(adc.getMaxPossibleReading());
Serial.print(F("numSamplesToAvg = ")); Serial.println(adc.getNumSamplesToAvg());
Serial.print(F("ADCSpeedSetting = ")); Serial.println(adc.getADCSpeedSetting());
Serial.print(F("ADCClockFreq (Hz) = ")); Serial.println(adc.getADCClockFreq()); //Hz
Serial.println(""); //new line
}


Γράφημα που δείχνει τις καμπλύλες για τα παραπάνω παραδείγματα:

http://i.imgur.com/pQ8erjf.png

Ευχαριστώ πολύ για τον χρόνο σας!

selectronic
01-04-17, 12:20
Κανείς?

Τουλάχιστον μπορεί κάποιος να επιβεβαιώσει ότι είναι φυσιολογικό το "σφάλμα" που έχω, στο κάτω-κάτω ένας κινέζικος AVR των <2€ είναι... Αν το πρόβλημα είναι ότι έχω μη-ρεαλιστικές προσδοκίες σχατικά με την ακρίβεια μέτρησης, θα ήθελα τουλάχιστον να το ξέρω :)

Ιν όδερ νιούζ, άλλαξα κάπως τον τρόπο που "καλιμπράρω" την μέτρηση, αλλά δεν έχει και πολύ νόημα αν το εύρος (=ακρίβεια μέτρησης) είναι 0-1023:

Από:
average = average2 / count;
average = average + 2;
float voltage2 = ((float) average / 1024.0) * Vref11;

πήγα σε:
average = average2 / count;
if (average >= 1 && average <= 30) {average = (average + 2);}
if (average >= 31 && average <= 350) {average = (average + 1);}
average = average + 1;
float voltage2 = ((float) average / 1024.0) * Vref11;

Για την default μέτρηση σε 10bit πάντα.

Σε κάθε περίπτωση πάντως το default "βήμα" όμως είναι κάπως μεγάλο (αν θέλω να μετρήσω πχ 50V μέσω διαιρέτη), στα ~1mV...

nkarama
01-04-17, 13:18
Προφανώς το έχεις ψάξει, αλλά να κάνω μια χαζή ερώτηση? με τι μετράς τις τάσεις? πως μπορείς να είσαι σίγουρος ότι η μη γραμμικότητα δεν οφείλετε στο όργανο μέτρησης?

Επίσης, μήπως εφόσον μετράς τέτοια μεγέθη, να πας σε έναν εξωτερικό ADC και εξωτερικό reference?

selectronic
01-04-17, 13:36
Προφανώς το έχεις ψάξει, αλλά να κάνω μια χαζή ερώτηση? με τι μετράς τις τάσεις? πως μπορείς να είσαι σίγουρος ότι η μη γραμμικότητα δεν οφείλετε στο όργανο μέτρησης?

Χμ, το μόνο που έχω για σύγκρισή είναι η μέτρηση το πολύμετρου, το "gadget-παλμογράφος" δεν μπορεί να μετρήσει mV με ακρίβεια... :/



Επίσης, μήπως εφόσον μετράς τέτοια μεγέθη, να πας σε έναν εξωτερικό ADC και εξωτερικό reference?
Το να πάω σε εξωτερικό ADC είναι μία λύση που θα μπορούσα να λάβω υπ' όψιν αν ήξερα 100% ότι έχω φτάσει το όριο του συγκεκριμένου AVR (που δεν το ξέρω)...

selectronic
01-04-17, 13:51
Το θέμα είναι ότι θέλω να φτιάξω ένα βολτόμετρο, που θα μετράει περίπου 0-50Vdc (μέσω πχ 1:10 divider)

θέλω λοιπόν, πέραν του θέματος της γραμμικότητας της μέτρησης Αναλογικού Πιν, να βελτιώσω την ακρίβεια της μέτρησης, ώστε να έχω τουλάχιστον 10mV ακρίβεια, αν μπορώ φυσικά (χωρίς να χρειαστεί να βάλω OpAmp κτλ).

Γι' αυτό δοκίμασα και την "NewAnalogRead" Βιβλιοθήκη, για να πάω στα πχ 0-4092 "βήματα" ADC, ώστε να έχω καλύτερη ακρίβεια όταν η τάση τθα έρθει από έναν 1:10 διαιρέτη.

Nemmesis
01-04-17, 15:15
Το θέμα είναι ότι θέλω να φτιάξω ένα βολτόμετρο, που θα μετράει περίπου 0-50Vdc (μέσω πχ 1:10 divider)

θέλω λοιπόν, πέραν του θέματος της γραμμικότητας της μέτρησης Αναλογικού Πιν, να βελτιώσω την ακρίβεια της μέτρησης, ώστε να έχω τουλάχιστον 10mV ακρίβεια, αν μπορώ φυσικά (χωρίς να χρειαστεί να βάλω OpAmp κτλ).

Γι' αυτό δοκίμασα και την "NewAnalogRead" Βιβλιοθήκη, για να πάω στα πχ 0-4092 "βήματα" ADC, ώστε να έχω καλύτερη ακρίβεια όταν η τάση τθα έρθει από έναν 1:10 διαιρέτη.

50V με ακρίβεια 10mv μας δίνει 50/0,01 = 5000 διαφορετικές διακριτές τιμές που σημαίνει ότι και με πραγματικό 12bit adc δεν μπορείς να έχεις αυτό που θέλεις... πόσο μάλλον με το 10bit του arduino... 50V /1024 σου δίνει ανάλυση 48mV στην καλύτερη των περιπτώσεων... και δεν έχουμε μιλήσει ακόμα καθόλου για την συχνότητα δειγματολειψιας και τυχών φιλτράρισμα του σήματος (και δεν εννοώ "να βάλουμε ένα πυκνωτακι").... καλό πράγμα τα arduino αλλά το κακάο είναι οτι ο καθε πληροφορικαριος νομίζει οτι μπορεί να γίνει ηλεκτρονικός.. conversion time σου λέει κάτι?
θέλει διάβασμα αρκετό... πριν από όλα διάβασε το datasheet του μΕ που φοράει το arduino σου πάνε δες τι παίζει ακριβώς με τα adc του και τι χρειάζεται να προσέξεις και μετά ψάξε πως αυτό μπορεί να γίνει μέσο του arduino IDE...

Nemmesis
01-04-17, 15:29
Γι' αυτό δοκίμασα και την "NewAnalogRead" Βιβλιοθήκη, για να πάω στα πχ 0-4092 "βήματα" ADC, ώστε να έχω καλύτερη ακρίβεια όταν η τάση τθα έρθει από έναν 1:10 διαιρέτη.

διάβασες καθόλου τι κάνει αυτή η lib??? θα σου έλεγα να διαβάσεις αυτό εδω (http://www.atmel.com/Images/doc8003.pdf)

Kernel Panic
01-04-17, 19:30
Νομίζω ότι είναι ποιο σωστή η διαίρεση να γίνει με το 1023 μιας και το 0 είναι επίσης αριθμός.
Sorry αλλά Είμαι με το κινητό και αυτό δεν με βοηθάει να δω ποιο καλά τον κώδικα.

pstratos
01-04-17, 19:59
Κάπου είχα γραψει πως μπορείς να φτιαξεις μια συναρτηση μεταφορας με το excel. Ηταν σε thread σχετικά με pwm έξοδο. Το βραδυ λεπτομερειες.....

Kernel Panic
01-04-17, 20:19
http://www.gammon.com.au/adc

selectronic
01-04-17, 23:18
Nemmesis την έχω κάνει την διαίρεση και ξέρω ότι ακόμα και αν δουλεύει 100% σαν 12bit το "κόλπο" με το oversample δεν θα έχω 10mV ακρίβεια, η τιμή των "10mV" είναι στο περίπου. Αυτό που είδα μετρώντας 0-1V είναι ότι αν πάω στα 0-50V μέσω διαιρέτη δεν θα έχω ~50mV ακρίβεια όπως θα έπρεπε θεωρητικά, αλλά κάπου στα 100mV, οπότε τα πχ 12.3V μπορεί να τα διαβάζει 12.2V ή 12.4V και αυτό είναι κομματάκι πολύ σφάλμα για εμένα... Θα προτιμούσα να γράφω στην LCD με δεύτερο δεκαδικό και να έχω τουλάχιστον 2-3 βήματα για 100mV, το οποίο θα γινόταν με 12bit πιστεύω.
Ναι διάβασα τι κάνει η βιβλιοθήκη. Όχι όλο το pdf αλλά αρκετά για να καταλάβω (?) πως δουλεύει και το πως δεν δουλεύει αν δεν υπάρχει "θόρυβος" στο σήμα μέτρησης κτλ, που φυσικά θα έχω γιατί ότι φτιάξω θα είναι σε διάτρητη και όχι σε PCB διπλής όψεως με Ground Plane και τα συναφή.
Ξαναλέω ότι είδα διαφορά στις μετρήσεις με την χρήση της βιβλιοθήκης.

Ο λόγος που ξεκίνησα αυτό το thread όπως λέει και ο τίτλος είναι η μη-γραμμικότητα στην μέτρηση. Στο άλλο thread που είχα θέμα μη-γραμμικότητας ο FILMAN έγραψε ότι θα έπρεπε να έχω γραμμική σχέση (http://www.hlektronika.gr/forum/showthread.php?t=88586&p=803935&viewfull=1#post803935) και τελικά ήταν στο κύκλωμα (hardware) το πρόβλημα, έτσι και τώρα είπα ότι ίσως κάνω κάτι λάθος στον κώδικα (κύκλωμα ουσιαστικά δεν υπάρχει) αφού μόνο 1 μήνα εμπειρία έχω με τους Arduino και είπα "δεν ανεβάζω τον κώδικα και τις μετρήσεις που έχω μήπως κάποιος μου ανοίξει τα μάτια?"...


Kernal Panic το link του έβαλες είναι ένα από τα 3-4 πιο χρήσιμα που βρήκα, ανάμεσα στα παααααρα πολλά που διάβασα στην φάση του Googlαρίσματος, που ήταν οι βδομάδες που περίμενα να παραλάβω τους Arduino από την Κίνα... Ιδιαίτερα το κομμάτι του "float voltage = ((float) rawADC + 0.5 ) / 1024.0 * Vref;" το έχω κάνει κλόπι-paste τελείως, ακριβώς αυτό χρησιμοποιώ! Σε αυτό το άρθρο είδα μεταξύ άλλων την μέθοδο του να προσθέτει μία "φιξ" τιμή στην "raw" μέτρηση του ADC: αυτός έχει "0.5" στον κώδικα, εγώ είχα "1.2" σε έναν Arduino και "2.0" σε άλλον, που είναι και στον κώδικα του πρώτου ποστ.
Επίσης εκεί χρησιμοποιεί "1024" αντί του "1023", αλλά πάνω σε αυτό δεν βρήκα "σίγουρη" απάντηση όταν το έψαχνα: μισοί λέγανε 1024, και άλλοι τόσοι 1023... Η αλήθεια είναι ότι δεν θυμάμαι γιατί κατέληξα να χρησιμοποιώ 1024, μάλλον θα είχα καλύτερα αποτελέσματα με αυτό. Θα κάνω δοκιμή και με 1023 όμως, ίσως αυτό να βελτιώσει την γραμμικότητα!

Σας ευχαριστώ για τις απαντήσεις :)

Nemmesis
02-04-17, 17:25
τα 10bit "μετρανε" απο 0-1023 αρα εχουμε 1024 διακριτες τιμε... τοσο απλο ειναι... με το 1024 ειναι σωστο...

SProg
02-04-17, 17:40
1023 ειναι το σωστο.


Η μονη περιπτωση που θα σου χρειαζοταν το 1024 θα ηταν εαν ηθελες να βρεις το βημα.


Προφανως το οτι το 1024 σε βολευει...δε σημαινει οτι ειναι το σωστο.

Fire Doger
02-04-17, 18:09
value = (adc/1023)*Vref
Αν το adc είναι ίσο με Vref σου επιστρέφει 1023. Στον παραπάνω τύπο το value θα είναι όντως ίσο με Vref. Αν είχαμε 1024 τότε το value θα ήταν μικρότερο.

Δεν είμαι σίγουρος αν η πραγματική τιμή είναι + - (Vref/2048) δηλαδή + - το μισό ενώς βήματος ή το adc κάνει στρογγυλοποίηση μόνο πρός τα πάνω ή κάτω.

Nemmesis
02-04-17, 19:08
1023 ειναι το σωστο.


Η μονη περιπτωση που θα σου χρειαζοταν το 1024 θα ηταν εαν ηθελες να βρεις το βημα.


Προφανως το οτι το 1024 σε βολευει...δε σημαινει οτι ειναι το σωστο.

καταρχάς δεν με βολέυει τίποτα και μάθε να γράφεις πιο σωστά... οκ? διαβασσε και λιγο για να μάθεις γιατι με το 1024 έχεις καλήτερα αποτελέσματα...

http://www.electro-tech-online.com/threads/why-adc-1024-is-correct-and-adc-1023-is-just-plain-wrong.132570/

SProg
02-04-17, 19:24
Μαλλον δεν ξερεις να διαβαζεις, εγω ξερω και να διαβαζω και να γραφω.Επισης ξερω που και σε ποιον απανταω.




Επίσης εκεί χρησιμοποιεί "1024" αντί του "1023", αλλά πάνω σε αυτό δεν βρήκα "σίγουρη" απάντηση όταν το έψαχνα: μισοί λέγανε 1024, και άλλοι τόσοι 1023... Η αλήθεια είναι ότι δεν θυμάμαι γιατί κατέληξα να χρησιμοποιώ 1024, μάλλον θα είχα καλύτερα αποτελέσματα με αυτό.

Nemmesis
02-04-17, 20:03
Μαλλον δεν ξερεις να διαβαζεις, εγω ξερω και να διαβαζω και να γραφω.Επισης ξερω που και σε ποιον απανταω.


δηλαδη θελεις να μου πεις οτι με το ποστ σου #13 δεν επαντας στο δικο μου #12 αλλα στου sele #11?? και άντε πες ειναι έτσι... μόνο εσύ ξέρεις που απαντάς εάν δεν βαλεις quote και επίσης όταν δεν υπάρχει quote στην ουσία δείχνεις να απαντάς στον προηγούμενο σου... και αφου ξέρεις να διαβάζεις, διάβεσε γιατι με το 1024 έχουμε μικρότερο error.. εσένα βολέυει το 1023 που δεν ειναι το σωστό ομως....

pstratos
02-04-17, 20:05
Βρήκα ενα παλιό (2005 παρακαλώ) projectaki με AVR και τον ενσωματωμένο ADC. Γράφω τα βασικά σημεία που έχουν να κάνουν με τάση

#define AVER_CONST 200
unsigned int adc_data;
#define ADC_VREF_TYPE 0x00

Εδώ του είπαμε να χρησιμοποιεί εξωτερική τάση αναφοράς (βαλαμε 2500 mV // δε θυμάμαι τι chipaki)

// ADC interrupt service routine
#pragma savereg-
interrupt [ADC_INT] void adc_isr(void)
{
#asm
push r30
push r31
#endasm
// Read the ADC conversion result
adc_data=ADCW;
//PORTB.0=1;
#asm
pop r31
pop r30
#endasm
}


// Read the ADC conversion result
// with noise canceling
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
#asm
in r30,mcucr
sbr r30,__se_bit
cbr r30,__sm_mask
out mcucr,r30
sleep
cbr r30,__se_bit
out mcucr,r30
#endasm
return adc_data;
}

O ADC διαβάζει βάσει του δικού του interrupt, ώστε να ελαχιστοποιήσουμε το θόρυβο. Δηλ όταν διαβάζει το ADC το AVR σταμάταγε ρολόγια, ΙΟ, uart κλπ.

Εχουμε την εξης συνάρτηση, η οποία διαβάζει συνεχόμενα δείγματα και δίνει μέσο όρο. Το Ν μπορεί να είναι ~50-100


int read_channel(char channel,int n)
{ unsigned long int sum;

int i;
int average;

sum=0;
for (i=0;i<n;i++)
{
read_adc(channel);
sum=sum+adc_data;
}
average= sum/n;

return average;
}

Θα χρειαστούμε και την συναρτηση μετατατροπής σε mVolts

unsigned int mvolts (unsigned int adc)
{ int voltage;
double mvolts1;
double mult=2.4437927; //2500/1023 se mvolts
mvolts1= mult* adc;
voltage= (unsigned int)mvolts1;
return voltage;}


Οπότε στην main είχαμε (διαβαζαμε 4 κανάλια, με μεσο ορο δειγμάτων σε mVolts στις μεταβλητες V1,V2,V3,V4)

for(i=0;i<4;i++) average[i]=0;
while (1)
{

PORTB.0=1;
delay_ms(200);
PORTB.0=0;
for(i=0;i<4;i++) average[i]= read_channel(i,AVER_CONST);

V0=mvolts(average[0]);
V1=mvolts(average[1]);
V2=mvolts(average[2]);
V3=mvolts(average[3]);





Από οτι θυμάμαι μετά από 10+ χρόνια.......
Τα ADC των AVR ήταν θορυβόδη... 10bit αλλά στην πραξη 9βιτ και αν.....
Η εσωτερική τάση αναφοράς εξαρτώταν από την τάση τροφοδοσίας!!! Αναγκαστικά εξωτερική τάση αναφοράς, με τον δικό της μάλιστα regulator
Ακόμα και οι τάσεις που διάβαζε το AVR εξαρτιώντουσαν από το φορτίο στα άλλα pin - εξόδους.
Αρα για γλήγορες/χοντρες δουλειες με πατέντες κάτι κάνεις. Αν θες να γίνεις σοβαρός πας σε εξωτερικούς ADC /isp ή σε άλλες οικογένεις mcu :wiink:

SProg
02-04-17, 20:18
O ADC διαβάζει βάσει του δικού του interrupt, ώστε να ελαχιστοποιήσουμε το θόρυβο. Δηλ όταν διαβάζει το ADC το AVR σταμάταγε ρολόγια, ΙΟ, uart κλπ.


Σωστα.Το αναφερει στα datasheet σαν Noise Reduction Sleep.

selectronic
02-04-17, 23:02
Από ότι καταλαβαίνω δεν θα έχω την ακρίβεια που θέλω απλώς μετρώντας με τον ενσωματωμένο ADC όπως πίστευα... :/
Ακόμα θέλω όμως να φτιάξω το όργανο για το τροφοδοτικό με Arduino, γιατί εκτός από Βολτ και Αμπέρ θέλω να υπολογίζει και τα Βατ, οπότε μάλλον θα πρέπει να μάθω και πως δουλεύει η επικοινωνία με I2C/SPI και το κάνω με εξωτερικό ADC.

Έχω είδη πάρει 16bit DAC (http://www.ebay.com/itm/172354218577?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT&autorefresh=true)s να έχω να παίζω, έχει κάποιος να μου προτείνει κάποιο "απλό" ADC σε DIP πάντα, να δοκιμάσω να το δουλέψω?


EDIT:

...Η εσωτερική τάση αναφοράς εξαρτώταν από την τάση τροφοδοσίας!!! Αναγκαστικά εξωτερική τάση αναφοράς, με τον δικό της μάλιστα regulator...

Από τα όσα βρήκα και διάβασα στον μαγευτικό κόσμο του internet, η εσωτερική ~1.1V Vref (για ΑΤmega328) είναι αρκετά σταθερή... Επίσης ένα "απλό" LM385 (http://www.ti.com/lit/ds/symlink/lm385-adj.pdf) έχει 2% ακρίβεια ενώ ένα LT1086 Linear Regulator (http://cds.linear.com/docs/en/datasheet/1086ffs.pdf) στα πχ 5V μπορεί να είναι και κάτω από 1%. Όχι ότι δεν υπάρχουν πολύ καλύτερα από το LM385 για αυτούς που δεν φτιάχνουν απλός ένα "LCD βολτόμετρο" και όχι ότι θα έχω εγώ 0.1% ακρίβεια an χρησιμοποιούσα το LT1086, αλλά αν το φορτίο είναι μικρό και σταθερό, ένα LT1086 δεν θα μπορούσε να κάνει για Vref, με τα χαρακτηριστικά που έχει (Line/Load/Thermal regulation, Ripple Rejection κτλ)... Αν είμαι λάθος παρακαλώ διορθώστε με, να μαθαίνω :)

pstratos
02-04-17, 23:21
Από οτι θυμάμαι καλά adc σε dip σπανίζουν. Αλλά μην το δένεις κόμπο. Αύριο θα ρωτήσω τους ειδήμονες μήπως έχουν κατά νου κανένα "εύκολο" chip

selectronic
02-04-17, 23:25
Από οτι θυμάμαι καλά adc σε dip σπανίζουν. Αλλά μην το δένεις κόμπο. Αύριο θα ρωτήσω τους ειδήμονες μήπως έχουν κατά νου κανένα "εύκολο" chip

Ευχαριστώ :)

SProg
02-04-17, 23:28
Πανε σε οποιδηποτε Site (πχ Mouser) και βαλε τα καταλληλα φιλτρα (TH,χρονος μετατροπης,16bit ή οτι θες,SPI,κτλ).

selectronic
02-04-17, 23:40
Πολύ σωστό αυτό που λες, αλλά πιστεύω ότι είναι καλύτερο αν ρωτήσεις κάποιον που ξέρει και έχει δουλέψει τέτοια ολοκληρωμένα.
Πχ αν κάποιος θέλει έναν Liner Regulator στα 5V, με τον τρόπο που λες θα βρεθεί μπροστά σε μία λίστα με 50 διαφορετικούς, ενώ αν ρωτήσεις κάποιον, θα σου πει "πάρε ένα 7805" και τελείωσες (ή κάποιο άλλο νεότερο).

Έχω ψάξει έτσι, πχ για Logic Level MOSFET (5Vgs) σε ΤΟ-220 και βρήκα αμέτρητα (σε Digikey ή RS νομίζω), αλλά επειδή δεν με συμφέρει εμένα να παραγγείλω 2-3 MOSFET από αυτά τα μαγαζιά, έπρεπε να δω ξανάψαξω να δω ποία από αυτά έχει σε eBay (και να προσευχηθώ ότι δεν θα έρθουν μαϊμούδες). Τελικά βρήκα και πήρα IRLZ24 (https://www.vishay.com/docs/91326/sihlz24.pdf).

Ξαναλέω ότι ο τρόπος που λες είναι σωστός, αν δεν έχεις κάποιον πιο πεπειραμένο να ρωτήσεις και πρέπει να το ψάξεις μόνος σου. Όχι να κάτσει κάποιος άλλος να κάνει την ίδια δουλειά για εσένα, εννοώ να ξέρει να σου πει "πάρε το Χ". Αυτή είναι η γνώμη μου τουλάχιστον.

SProg
02-04-17, 23:52
Εαν βαλεις ακριβως τα χαρακτηριστικα που θελεις, δεν βγαζει τοσα.

Για αυτο που θελεις σε TH, η Mouser βγαζει < 10.Αν δεις και τις τιμες...οι επιλογες σου γινονται 2-3.


Θα σου προτεινα να πας σε SMD με 'ευκολο' package (ADS8319 (http://eu.mouser.com/new/Texas-Instruments/ti-ads8319-adc/)).Οι επιλογες σε σχεση με τα TH ειναι x20 σε τετοια ολοκληρωμενα.

pstratos
02-04-17, 23:55
Έκανα μια πρωτη έρευνα.
http://export.farnell.com/texas-instruments/ads7841p/ic-12bit-adc-7841-dip16/dp/1097415 4 καναλια Χ 12 bit ~6euro
http://export.farnell.com/maxim-integrated-products/max1416epe/adc-2-ch-sigma-delta-16bit-dip/dp/2513557 2 καναλια Χ 16 bit ~12euro

Ψάξε παραμετρικά και σίγουρα θα ακούσεις προτάσεις από "δουλεμένους" ADC.
Σκέψου και την περίπτωση άλλων packages, φτιάχνοντας μικρή "daughterboard". Κολλάς το "εξωτικό" chip και βάζεις pins ώστε να το καρφώσεις στο breadboard για δοκιμές

pstratos
02-04-17, 23:56
Από ότι καταλαβαίνω δεν θα έχω την ακρίβεια που θέλω απλώς μετρώντας με τον ενσωματωμένο ADC όπως πίστευα... :/
Ακόμα θέλω όμως να φτιάξω το όργανο για το τροφοδοτικό με Arduino, γιατί εκτός από Βολτ και Αμπέρ θέλω να υπολογίζει και τα Βατ, οπότε μάλλον θα πρέπει να μάθω και πως δουλεύει η επικοινωνία με I2C/SPI και το κάνω με εξωτερικό ADC.

Έχω είδη πάρει 16bit DAC (http://www.ebay.com/itm/172354218577?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT&autorefresh=true)s να έχω να παίζω, έχει κάποιος να μου προτείνει κάποιο "απλό" ADC σε DIP πάντα, να δοκιμάσω να το δουλέψω?


EDIT:


Από τα όσα βρήκα και διάβασα στον μαγευτικό κόσμο του internet, η εσωτερική ~1.1V Vref (για ΑΤmega328) είναι αρκετά σταθερή... Επίσης ένα "απλό" LM385 (http://www.ti.com/lit/ds/symlink/lm385-adj.pdf) έχει 2% ακρίβεια ενώ ένα LT1086 Linear Regulator (http://cds.linear.com/docs/en/datasheet/1086ffs.pdf) στα πχ 5V μπορεί να είναι και κάτω από 1%. Όχι ότι δεν υπάρχουν πολύ καλύτερα από το LM385 για αυτούς που δεν φτιάχνουν απλός ένα "LCD βολτόμετρο" και όχι ότι θα έχω εγώ 0.1% ακρίβεια an χρησιμοποιούσα το LT1086, αλλά αν το φορτίο είναι μικρό και σταθερό, ένα LT1086 δεν θα μπορούσε να κάνει για Vref, με τα χαρακτηριστικά που έχει (Line/Load/Thermal regulation, Ripple Rejection κτλ)... Αν είμαι λάθος παρακαλώ διορθώστε με, να μαθαίνω :)


Δεν θα ψάξεις για linear regulator αλλά για voltage reference :wiink:
Μάλιστα αν το πονηρευτείς πάρε με έξοδο 2.048 V ή κάτι άλλο ""στρογγυλό" :001_tt2:, ώστε να μειώσεις ακόμα περισσότερο το υπολογιστικό σφάλμα. Βέβαια όλα τα καλά κυκλοφορούν σε SOT23, δεν είναι δύσκολο να τους κολλήσεις τρία συρματάκια.....

Ισως το μόνο βολικό για breadboard to LM4040 στα 4.096V σε TO-92

selectronic
03-04-17, 00:09
Δεν θα ψάξεις για linear regulator αλλά για voltage reference :wiink:
Μάλιστα αν το πονηρευτείς πάρε με έξοδο 2.048 V ή κάτι άλλο ""στρογγυλό" :001_tt2:, ώστε να μειώσεις ακόμα περισσότερο το υπολογιστικό σφάλμα. Βέβαια όλα τα καλά κυκλοφορούν σε SOT23, δεν είναι δύσκολο να τους κολλήσεις τρία συρματάκια.....

Σωστά αυτά που λες, αλλά το εξωτερικό ADC δεν θα θέλει Vref έτσι? Θα μετράει τάση σε δύο ποδαράκια και θα στέλνει την μέτρηση στον Arduino μέσω X επικοινωνίας.

selectronic
03-04-17, 00:12
Με μία απλή και γρήγορη αναζήτηση, βρήκα φθηνό Quad Channel 16bit ADC με I2C επικοινωνία: ADS1115 (http://www.ebay.com/itm/16-Bit-I2C-ADS1115-Module-ADC-4-channel-with-Pro-Gain-Amplifier-for-Arduino-RPi-/201540483080?hash=item2eecbfb808:g:N3cAAOSwIgNXiFo H), ένα από τα πάμπολα modules για Arduino. Datasheet (https://cdn-shop.adafruit.com/datasheets/ads1115.pdf)

https://cdn-shop.adafruit.com/970x728/1085-03.jpg

εδώ το μικρότερο 12bit ADS1015:

https://cdn-learn.adafruit.com/assets/assets/000/036/145/original/sensors_schem.png?1475541078

pstratos
03-04-17, 00:30
Πολύ ωραίο. Τελικά σε arduino module έχουν φτιάξει σχεδόν τα πάντα :001_smile:. Εγκυκλοπαδικά πολλοί ADC έχουν ενσωματωμένη την Vref. Στις καλές όμως εφαρμογές προτιμούμε την εξωτερική ώστε να έχουμε οτι επιλογή θέλουμε σχετικά με τιμή, ακρίβεια, σταθερότητα, κλπ,κλπ. Μην σας πώ και για εφαρμογές που πραγματικά δεν μας νοιάζει η Vref αυτή καθ'αυτή αλλά ο λόγος δύο τάσεων (ratiometric input), οπότε η ίδια η Vref είναι μια ακόμα είσοδος (μακραν offtopic)

selectronic
03-04-17, 00:40
Εμένα δεν είναι "καλή εφαρμογή", είναι πιο κοντά στο "κάνοντας το βήμα από Lego σε Arduino" :biggrin:
Θα παραγγείλω ένα τέτοιο λοιπόν και θα αρχίσω το διάβασμα για I2C επικοινωνία. Στο τέλος θα πάω και σε Mega 2560, με τόσες βιβλιοθήκες (LiquidCrystal, TimerOne και τώρα όποια είναι για I2C) δεν θα μείνει χώρος για το πρόγραμμα XD. Θα πάρω και δύο W25Q64BV Serial Flash Memory (http://www.ebay.com/itm/172468988798?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT) να έρχονται, αχρείαστα να είναι...

pstratos
03-04-17, 01:01
Ξεκίνα λοιπόν από εδώ

http://www.atmel.com/Images/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf

και ξεζουμισε το. Καλές οι ευκολίες του arduino αλλά η καρδιά είναι ο mcu. 256K flash έχει. Τι θα φτιάξεις και φοβάσαι μην και δεν σου φτάσει? Με 16ΚΒ ήμασταν και φτιάχναμε πράμα.... εκτός αν θες να βάλεις κανα rtos ή γραφικά σε lcd

selectronic
03-04-17, 01:28
Όχι, εγώ έχω τρεις Nano 5V και ένα Mini Pro 3.3V (κινέζικους) που έχουν τον ATmega328 με 32KB... Γι αυτό λέω ότι στο τέλος θα πρέπει να πάω σε 2560, γιατί δεν θα φτάσουν. Που δεν είναι τόσο ακριβός στα περίπου 7 ευρώ (http://www.ebay.com/itm/1pcs-Mega-2560-ATmega2560-16AU-Board-Free-USB-Cable-For-Arduino-/171932304813?hash=item2807f6c5ad:g:ExUAAOSwuTxV9h9 j), αλλά τόσα ποδαράκια "χαμένα", και με τον Nano ούτε τα μισά δεν θα δουλεύω, άσε που είναι και πολύ μεγαλύτερη πλακέτα... Στο δικό μου μυαλό θα ήταν πιο σωστό να προσθέσω μνήμη αν αυτό είναι το πρόβλημα, αλλά επειδή τώρα μαθαίνω τον Arduino και μάλλον θα μου παίσουν πολλά όλα αυτά, μάλλον αν δεν μου φτάσει η μνήμη θα πάω σε 2560 από το να βάλω εξωτερική flash. Αλλά παράγγειλα τα τσιπάκια, γιατί είναι φθηνά και αν τα χρειαστώ θα πρέπει να περιμένω ένα μήνα να έρθουν και περαστικά.

Και όλα αυτά ξεκίνησαν όταν είπα να φτιάξω αυτό (http://meettechniek.info/diy-instruments/arduino-wattmeter.html) για να έχω V/A/W στο τροφοδοτικό μου, αλλά τελικά δεν έβγαλα καθόλου άκρη με τον κώδικα και ξεκίνησα από το μηδέν... Με τα "read" "write" τα πάω καλά, αν είναι να ασχοληθώ με "MCUCR &= 0xEF" προτιμώ να βάλω ένα αναλογικό βολτόμετρο και τέλος. XD

selectronic
03-04-17, 11:14
Κύριοι λίγη ακόμα βοήθεια αν μπορείτε:

Ο παρακάτω κώδικας, που βρήκα εδώ (https://code.google.com/archive/p/tinkerit/wikis/SecretVoltmeter.wiki), μετράει την Vcc του Arduino χρησιμοποιώντας την εσωτερική ~1.1Vref
Από ότι κατάλαβα χρησιμοποιεί μία από τις 8 Αναλογικές Εισόδους για να το κάνει αυτό, και αν κατάλαβα καλά, η επιλογή γίνεται στο "ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);".
Πως μπορώ να αλλάζω την Αναλογική Είσοδο ???
Βρίσκω παντού (πχ εδώ (https://sites.google.com/site/qeewiki/books/avr-guide/analog-input)) ότι αυτά τα 4 "MUX" παίρνουν τιμές 0 ή 1 για να επιλέξεις Είσοδο, αλλά ούτε βλέπω κανένα 0 ή 1 στον κώδικα, ούτε 4ο MUX βλέπω (4 δεν είναι?) και τι σημαίνει το "_BV" ???

Αν μπορεί κάποιος να μου πει τι πρέπει να γράψω για να αλλάξει από πχ Α1 σε Α2 ή Α3 θα είμουν υπόχρεος...



long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL; readVcc |= ADCH<<8; readVcc = 1126400L / readVcc; // Back-calculate AVcc in mV

lcd.setCursor(0, 0);
lcd.print(readVcc, DEC);


http://i.imgur.com/DPOCgO1.png

nkarama
03-04-17, 11:53
Οπως βλέπεις ο κώδικας εκτελεί μια OR για να σετάρει τον καταχωρητή ADMUX.
"ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);".

Τα MUX είναι κάποιες έτοιμες bit-σειρές που χρησιμοποιούνται για ευκολία.
η Παραπάνω γραμμή θα σετάρει τον register με την εξής bit-σειρά...

010-1110
(το - είναι το 4ο bit του register το οποίο είναι αδιάφορο...)

Αν θες πχ τον register να σεταρειστεί με μια άλλη συμβολοσειρά πχ 010-0111 θα έγραφες το παρακάτω:

"ADMUX = _BV(REFS0) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0);"

Το τι ακριβώς κάνουν αυτά τα bits και ο register θα το βρεις στο datasheet του ATMEga328 .... Αλλά νομίζω και ο πίνακας το λέει καθαρά... ;)

selectronic
03-04-17, 11:59
Ευχαριστώ πολύ :)

nkarama
03-04-17, 12:12
Οσο για το _BV ψάξε στο google για _BV macro
Μια βοήθεια είναι για να κάνει τον κώδικα ευανάγνωστο...
Οπως επίσης και τα MUXn και τα υπόλοιπα είναι απλά defines των θέσεων των bit στους καταχωρητές. Αλλιώς θα έπρεπε να θυμάσαι τις θέσεις των bit by heart...

selectronic
03-04-17, 12:28
Γμτ είναι κάπως σαν να πρέπει να μάθω Κινέζικα για να διαβάζω μόνο ένα βιβλίο, και μετά να μην ξαναπιάσω ποτέ κάτι κινέζικο στα χέρια μου...
Όχι ότι ότι μαθαίνεις είναι άχρηστο φυσικά, αλλά ήλπιζα να την βγάλω καθαρή με την Basic που κουτσοθυμάμαι από το σχολείο: if αυτό, then κάνε το τάδε, κτλ.
Με τα "AnalogRead" και "lcd.print" κάτι γίνεται, αλλά να μάθω (λέω και κανένα αστείο να περάσει η ώρα) και C++ στα γεράματα, την κάτσαμε την βάρκα :lool:

nkarama
03-04-17, 12:54
Γμτ είναι κάπως σαν να πρέπει να μάθω Κινέζικα για να διαβάζω μόνο ένα βιβλίο, και μετά να μην ξαναπιάσω ποτέ κάτι κινέζικο στα χέρια μου...
Όχι ότι ότι μαθαίνεις είναι άχρηστο φυσικά, αλλά ήλπιζα να την βγάλω καθαρή με την Basic που κουτσοθυμάμαι από το σχολείο: if αυτό, then κάνε το τάδε, κτλ.
Με τα "AnalogRead" και "lcd.print" κάτι γίνεται, αλλά να μάθω (λέω και κανένα αστείο να περάσει η ώρα) και C++ στα γεράματα, την κάτσαμε την βάρκα :lool:

Δεν μπορείς να φανταστείς πόσο πολύ βοηθάει το να μάθεις να προγραμαμτίζεις έναν AVR ή άλλον μΕ. Απλά καταλαβαίνεις σε πόσο λάθος δρόμο είναι η πληροφορική σήμερα... Το hardware έχει γίνει τόσο φθηνό που πλέον χρησιμοποιείτε για να "κρύβονται" τα προβλήματα του software. Είναι αργή η εφαρμογή? ρίχτου περισσότερες CPU. Γεμίζει η μνήμη? αύξησέ την... Κανείς δεν κοιτάει να κάνει optimize τον κώδικα πλέον. Ολοι γράφουν λες και έχουν unlimited resources και το κακό μεγαλώνει συνέχεια...
Ενώ σε έναν 328 πρέπει να χωρέσεις το πρόγραμμά σου σε χ 32KΒ και να φροντίσεις οι μεταβλητές σου να μην ξεπεράσουν τα 2ΚΒ ή ο τρόπος που χρησιμοποιείς τα 2ΚΒ να είναι τέτοιος που να μην κατακερματίσεις την μνήμη και μετά δεν χωράει τίποτα. Και πρέπει στο τέλος και να δουλεέυει :)

selectronic
03-04-17, 13:34
Θυμάμαι που διάβαζα πριν χρόνια για το ίδιο πρόβλημα στα παιχνίδια των PC, ότι οι προγραμματιστές δεν έδιναν πολύ σημασία στο να γράψουν "γρήγορο" κώδικα γιατί σου έλεγαν "ας πάρει το νέο μοντέλο που είναι 2 φορές πιο γρήγορο και θα παίξει".
Πάντως σίγουρα είναι μεγάλο πράγμα να μπορείς να κάνεις κατασκευές μέσω μΕ και κώδικα, και ιδιαίτερα τώρα είναι η εποχή που οι Αtmel "πιάσανε" και υπάρχει κυριολεκτικά ότι module μπορείς να φανταστείς, άσε που ψωνίζουμε τώρα κατευθείαν από κίνα στο 1/10 της τιμής που θα αγοράζαμε παλιά. Αν γινόταν και να μην είχαμε χρεοκοπήσει...

Πάντως το γράψιμο κώδικα είναι τέχνη, θυμάμαι που λέγανε ότι οι Ρώσοι στα 80s ήταν καλοί στο να γράφουν κώδικα γιατί ο χρόνος που έδιναν στον καθένα μαθητή στο ΕΝΑ mainframe που είχε το πανεπιστήμιο ήταν πολύ λίγος και έπρεπε στην ουσία να τρέξουν τον κώδικα και να κάνουν debugging στο μυαλό τους, πριν ακόμα φτάσουν να ακουμπήσουν το πληκτρολόγιο!

Fire Doger
03-04-17, 14:44
Αν γράψεις σε asm να δεις διαφορά, βλέπεις πρόγραμμα 1kb και σου φαίνεται βουνό! Τότε καταλαβαίνεις πολλά πράγματα της C.
Και οι μΕ προς τον ίδιο δρόμο βαδίζουν, όπως από assembly πήγαμε σε C για ευκολία και ταχύτητα έτσι και τώρα πάνε σε RTOS.
Το κακό με το arduino είναι πως έχουν αρχίσει να θεωρούν τις αναπτυξιακές ως κομμάτι που μπορεί να μπεί σε εφαρμογή. Αν δείτε σε σελίδες με freelancer κάνουν όλη την δουλειά σε arduino και μετά ζητάνε να τους τα μετατρέψει κάποιος σε καθαρή C και να τους σχεδιάσει πλακέτα με καθαρό avr. Στο μέλλον που όλοι θα αγοράζουν με 5$ arduina με bga το να γνωρίζεις το hardware και να μπορείς να το σχεδιάζεις θα είναι μεγάλο προσόν! Δεν είναι πολύ μακριά, ήδη raspberry, beaglebone είναι μπροστά μας.
Και στην σχολή μου ήδη βλέπω άτομα που επενδύουν χρόνο μαθαίνοντας beaglebone και πιστεύουν ότι μαθαίνουν arm. Σαν να λες "ξέρω arduino άρα ξέρω avr"...
Μπράβο σου που το παλεύεις με C και όχι με wiring!

*Άμα οι avr "πιάσανε" τότε γιατί η Microchip αγόρασε την Atmel? :P

pstratos
03-04-17, 17:11
Οι AVR και καλά πιάσανε οταν οι arduinoi διάλεξαν AVR και οχι PIC. Αν ρωτήσεις έξω πολλοί δεν ξέρουν τι mcu φοράει το board. Πάντως το να μάθεις έναν mcu σε κάνει να μάθεις αρχιτεκτονική, τεχνικές προγραματισμού, βελτιστοποίηση, αναλογικά, ψηφιακά ......

nkarama
03-04-17, 18:32
καλά εσείς το πήγατε πολύυυυ μπροστά...
υπάρχει κόσμος που κάνει μια χαρά την δουλειά του με τις ευκολίες που προσφέρει η arduino-γλωσσα αλλά και η υλοποίηση του arduino (κατευθείαν USB σύνδεση χωρίς programmers ή άλλα εξωτικά για τον καθημερινό χρήστη υλικά).

Αυτοί λοιπόν οι χρήστες, έμειναν στο arduino λόγω ακριβώς αυτής της ευκολίας της γλώσσας. Επειδή δεν τους τρόμαξαν με register, με bits, με fuses κ.ο.κ. Πολύ πιθανό αν είχαν δει την πολυπλοκότητα που υπάρχει κάτω απο το καπό να την είχαν κάνει με ελαφρά....
Τώρα, απο αυτούς που έμειναν, ένα ποσοστά θα αποφασίσει να το "ψάξει" παραπάνω για να κάνει μερικά πραγματάκια γρηγορότερα και καλύτερα με την απλή C του ελεγκτή. Αλλά μέχρι εκεί...
Δεν πιστεύω κανείς απο αυτούς να πιάσει την assembly όσο καλύτερα και γρηγορότερα μπορούν να γίνουν τα πράγματα...
Δεν θέλουμε να γίνουμε όλοι ηλεκτρονικοί με ειδικότητα στα ψηφιακά... θέλουμε να κάνουμε γρήγορα και εύκολα την δουλειά μας, το χόμπυ μας κτλ κτλ...

manolena
03-04-17, 21:35
Νομίζω πως ο ορθός δρόμος για να μάθει κάποιος προγραμματισμό, είναι να ακολουθήσει τη φυσική σειρά των πραγμάτων, όπως αυτή αναπτύχθηκε με τα χρόνια. Το λέω σαν προσωπική άποψη, μαθαίνοντας, γράφοντας και αναπτύσσοντας προτζεκτάκια σε assembly (όχι μόνο σε ένα brand μ/Ε), μετά σε ανώτερη γλώσσα όπως C ή Wiring. Νομίζω επίσης πως είναι αρκετά δυκολότερο (εντούτοις όχι ακατόρθωτο) να γίνει το αντίστροφο. Έπειτα, είναι και θέμα γούστου. Η όρεξη του καθενός είναι καθαρά υποκειμενικό ζήτημα.

nkarama
03-04-17, 21:42
Μάνο εσύ δηλαδή έμαθες πρώτα assembly και μετά basic?
Για σκέψου το...

manolena
03-04-17, 22:21
Όχι όχι, εγώ δεν τα είπα όπως έπρεπε. Απο assembly κατ΄ευθείαν, και πάνω. Δίκιο έχεις εσύ, η σειρά είναι όπως τα λές.

selectronic
03-04-17, 23:37
...Μπράβο σου που το παλεύεις με C και όχι με wiring!...

Όπως είδες καθόλου δεν το παλεύω, στο πρώτο κομμάτι C που είδα, Googlισα κανένα τέταρτο της ώρας και μετά είπα "όχι πάλι θεέ μου, δεν χρειάζεται να μάθω τι κάνουν όλα αυτά: Ας μου πει απλός κάποιος συνάνθρωπος απλώς πως να το αλλάξω για να ξεπεράσω αυτό το κομμάτι και συνεχίζω στον εύκολο "Arduinάτο κώδικα" που ψιλό-έμαθα!". Αν και από τότε που έγραψα το τελευταίο ποστ δεν τον ξανάπιασα τον Arduino, θέλω να πιστεύω ότι δεν θα ξαναχρειαστεί να ακουμπήσω τέτοιον κώδικα.
Πιστεύω ότι το σωστό είναι να μαθαίνεις όσα μπορείς και σίγουρα ότι μαθαίνεις δεν πάει χαμένο, αλλά τυχαίνει εγώ να μην είμαι στην φάση της ζωής μου που το να κάτσω να μάθω μία "δύσκολη" γλώσσα μου είναι ευχάριστο. Με τα Arduinάτα* δυσκολεύτηκα όπως είναι φυσικό αλλά μου άρεσε, για τον πιο "σκληροπυρηνικό" κώδικα αν και πιστεύω ότι θα μου έδινε την ίδια ικανοποίηση το να τον μάθω, απλώς δεν έχω τον χρόνο/όρεξη για να ασχοληθώ, ιδιαίτερα αν δεν είναι και κάτι που θα μου ήταν χρήσιμο επαγγελματικά (υποθέτοντας ότι δεν θα αλλάξω επάγγελμα έτσι). Ίσως πριν μία δεκαετία να ήταν αλλιώς τα πράγματα.

Τώρα εγώ είπα απλός να παίξω λίγο με τον Arduino αφού είναι φθηνός κτλ, για το αν άλλοι ξεκινάν να φτιάξουν πχ PLC με Arduino και μετά όταν τελειώσει ο σχεδιασμός κάθονται/ζητάνε να το ουσιαστικά ξανά-φτιάξουν αλλά "πιο σωστά" τι να πω, εγώ το βλέπω διπλή δουλειά χωρίς λόγο...

*Τελικά πως λέγεται αυτός ο κώδικας ???


...Οι AVR και καλά πιάσανε οταν οι arduinoi διάλεξαν AVR και οχι PIC...

...καλά εσείς το πήγατε πολύυυυ μπροστά...
υπάρχει κόσμος που κάνει μια χαρά την δουλειά του με τις ευκολίες που προσφέρει η arduino-γλωσσα αλλά και η υλοποίηση του arduino (κατευθείαν USB σύνδεση χωρίς programmers ή άλλα εξωτικά για τον καθημερινό χρήστη υλικά).
Αυτοί λοιπόν οι χρήστες, έμειναν στο arduino λόγω ακριβώς αυτής της ευκολίας της γλώσσας. Επειδή δεν τους τρόμαξαν με register, με bits, με fuses κ.ο.κ. Πολύ πιθανό αν είχαν δει την πολυπλοκότητα που υπάρχει κάτω απο το καπό να την είχαν κάνει με ελαφρά...

Θυμάμαι πριν μερικά χρόνια τους PIC όπως πχ 16f84 αλλά αυτοί δεν πιάσανε. Γιατί δεν πιάσανε και τι διαφορά υπάρχει μεταξύ AVR και PIC, δεν έχω ιδέα, αλλά νομίζω ότι και αυτοί είχαν εύκολη γλώσσα στον προγραμματισμό τους.

Πέραν όμως των χαρακτηριστικών (πόσες εισόδοι/εξόδοι, τι ταχύτητα, τι "ευκολίες" όπως PWM) αυτό που έγραψε ο nkarama είναι η αλήθεια: βλέπεις τον κώδικα του Arduino με τα "Print(x) / Write(x)" και λες θα το παλέψω όταν είσαι χομπίστας και το κάνεις για την πλάκα σου, αν πχ εγώ έβλεπα μόνο κώδικα τύπου "ADCSRA |= _BV(ADSC)" δεν θα είχα ασχοληθεί γιατί δεν μου χρειάζεται ο Arduino: θα αγόραζα ένα έτοιμο "Volt/Amp/Watt LCD Meter" και θα έκανα την δουλεία μου. Και αυτοί που θα ήθελαν/γούσταραν/έπρεπε να μάθουν να δουλεύουν τον Arduino, θα τον μάθαιναν, όπως και τώρα.

pstratos
03-04-17, 23:48
Οι πιο πολλοί ασχολήθηκαν με μΕ όταν φτάσαν σε σημείο να μην τους καλύπτουν τα απλά διακριτα ψηφιακά/αναλογικά ηλεκτρονικά. Δηλ αρχικά φτιάχνεις με τρανζιστοράκια, μετά με λογικές πύλες και πάει λέγοντας. Όταν φτάσεις σε μια πλακέτα να έχεις καμιά 20 ολοκληρωμένα ο μΕ έρχεται σαν φυσική συνέχεια - και ας προγραμματίζεις assembly. Κάποια στιγμή βλέπεις οτι υπάρχει η δυνατότητα για ansi-C στον μΕ και κάνεις παπάδες. Η arduino-κατάσταση καμία σχέση με την παραπάνω καμπύλη εκμάθησης.

Fire Doger
04-04-17, 00:02
Εγώ πιστεύω καλύτερα να ξεκινήσει κάποιος με C και να πάει παρακάτω.

Εφόσον είχα την εμπειρία να λύσω το πρόβλημα και να σχεδιάσω το διάγραμμα ροής στο μυαλό μου, το επόμενο βήμα ήταν να έρθω κοντά στο hardware και η assembly είναι η καλύτερη επιλογή όχι όμως η μόνη. Για αυτό κάποιος μαθαίνει assembly (άντε και να στήνει inline καμιά κρίσιμη ρουτίνα). Αν κάποιος δεν έχει ιδέα από προγραμματισμό η assembly είναι η χειρότερη επιλογή γιατί μαθαίνει 2 σε 1.

Τώρα που ξέρω το hardware μου ότι και να θέλω να κάνω θα κοιτάξω το λεξικό της C και θα βρω την σωστή λύση, αν δεν mου φτάνει η ταχύτητα του μΕ παω σε άλλον όχι σε asm.
Δικιά μου άποψη είναι ότι όποιος θέλει να ασχοληθεί να μάθει το hardware (είτε με C, είτε με wiring, είτε με binary) για να μπορεί να κάνει ότι του κατέβει στο κεφάλι. Τα διαβάζει 1 φορά, τα μαθαίνει, τα ξέρει για πάντα.

Άμα θες περίεργα ψάρια μαθαίνεις να ψαρεύεις, αλλιώς ότι σου δώσει έτοιμο ο ψαράς.
Ότι δουλεύει για τον καθένα καλό είναι!:wiink:

selectronic
04-04-17, 04:40
Τα προβλήματα μου ακόμη κι όταν παλεύω μόνο 5 γραμμές κώδικα συνεχίζονται στον μαγευτικό κόσμο του Arduino:

Προσπαθώ απλός να αντιγράψω τον κώδικα που είχα βρεί (link (https://code.google.com/archive/p/tinkerit/wikis/SecretVoltmeter.wiki)) για να μετράω την Vcc.
Έχω δύο κομμάτια, το ένα που κάνει όλη την μαγεία και φυλάει το αποτέλεσμα σαν "readVcc", και το δεύτερο απλός τυπώνει το αποτέλεσμα στην LCD, τόσο απλά.
Όταν είναι και τα δύο παρεΐτσα στο "void loop ()" δουλεύει και μου δίνει πχ "4712" στην οθόνη (εκτός του timer) αφού όμως τυπώσει μία και μόνο φορά στην αρχή "-1" (ίσα που προλαβαίνεις να το δεις με αυτές τις τιμές delay). Μετά έχω πάντα "4712", δεν αλλάζει. Δεν είναι σωστή η μέτρηση των 4712mV αλλά θα γίνει ρεγουλάρισμα του "readVcc = 1126400L / readVcc;" όταν με καλό δουλέψει ο κώδικας όμως.


#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 4, 6, 7, 8, 9);

void setup()
{
lcd.begin(20, 2);
}

void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);

long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(100);
ADCSRA |= _BV(ADSC);
readVcc = ADCL; readVcc |= ADCH<<8; readVcc = 1126400L / readVcc;

lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(readVcc);
delay(100);
}

Όμως εγώ δεν θέλω να μετράω συνεχώς την Vcc αλλά μόνο μία φορά στην αρχή, οπότε να μετρήσει μία φορά και μετά να έχω το αποτέλεσμα στην μεταβλητή "readVcc" για να κάνω στο loop πράξεις.
*Το ξέρω ότι μπορεί να είναι λάθος μου να πιστεύω ότι δεν θα αλλάξει η Vcc κατά την λειτουργία του κυκλώματος, αλλά αυτό είναι άλλο θέμα, ας μην ασχοληθούμε με αυτό τώρα.
Κάνω λοιπόν copy-paste τον κώδικα στο setup καιιιιιιιι........ τζίφος. Ο 100% ίδιος κώδικας στο setup, δίνει "-1" στην LCD :(

#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 4, 6, 7, 8, 9);

void setup()
{
lcd.begin(20, 2);

long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(100);
ADCSRA |= _BV(ADSC);
readVcc = ADCL; readVcc |= ADCH<<8; readVcc = 1126400L / readVcc;

lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(readVcc);
delay(100);
}

void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);
}

Αυτό το -1 στην αρχή λέω είναι, ας μεγαλώσω το delay. Αλλά ακόμα και 5000 + άλλα 5000 μετά καθυστέρηση να βάλω όπως παρακάτω, πάλι "-1" έχω...

long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(5000);
ADCSRA |= _BV(ADSC);
readVcc = ADCL; readVcc |= ADCH<<8; readVcc = 1126400L / readVcc;
delay(5000);

Και τώρα το κερασάκι στην τούρτα: Αν κρατήσω το κομμάτι της μέτρησης στο setup και πάω απλός να τυπώσω την readVcc στο loop, δεν περνάει από compile, μου λέει "δεν μου δήλωσες ποτέ τι είναι αυτό το 'readVcc' που θες να τυπώσεις" !!! Πως είναι δυνατόν, αφού το "long readVcc;" δεν άλλαξε θέση! Μόνο το κομμάτι που του ζητάω να μου τυπώσει την μεταβλητή μετέφερα, και στο loop, όχι σε τίποτα functions ή κάτι περίπλοκο...

Αυτός ο κώδικας:

#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 4, 6, 7, 8, 9);

void setup()
{
lcd.begin(20, 2);

long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(100);
ADCSRA |= _BV(ADSC);
readVcc = ADCL; readVcc |= ADCH<<8; readVcc = 1126400L / readVcc;
}

void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);

lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(readVcc);
delay(100);
}

Βγάζει μήνυμα: 'readVcc' was not declared in this scope

Arduino: 1.6.5 (Windows 7), Board: "Arduino Nano, ATmega328"

sketch_apr04b.ino: In function 'void loop()':
sketch_apr04b:35: error: 'readVcc' was not declared in this scope
'readVcc' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.

Μετά μου λέτε για C++ και Assembly... :crying:

selectronic
04-04-17, 05:14
Εύρηκα!

Βρήκα τον ίδιο κώδικα σε άλλη σελίδα (http://www.polarsys.ca/docs/arduino/voltage.html), και είδα ότι το copy-paste δεν πέτυχε την πρώτη φορά και έβαλα μια γραμμή σαν σχόλιο... Τώρα ο παρακάτω κώδικας δουλεύει είτε τον βάλω στο setup είτε στο loop αλλά ακόμα έχω το ίδιο πρόβλημα όταν το βάζω μισό και μισό... Γιατί "χάνεται" η μέτρηση και αποθήκευση της "readVcc" όταν το μόνο πράγμα που αλλάζει στον κώδικα είναι το πότε τυπώνω την εν λόγο μεταβλητή ???



long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10);
ADCSRA |= _BV(ADSC);
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL; readVcc |= ADCH<<8; readVcc = 1126400L / readVcc;

lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(readVcc);
delay(100);

manolena
04-04-17, 07:36
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(readVcc);
delay(100);


Αυτό στο κάνει γιατί πριν εμφανίσεις την τιμή για 100ms(!), "καθαριζεις" πρώτα την προηγούμενη με μία lcd.clear();

Βάλε αυτή την εντολή (την lcd.clear() εννοω) ακριβώς μετά την lcd.print(readVcc);
... έτσι ώστε ακόμα και να αλλάζουν τα δεκαδικά ψηφία να σου καθαρίζει την ουρά.

Επίσης η delay(100) νομίζω είναι πολύ λίγη, θα σου αλλάζει πολύ γρήγορα τιμές. Βάλε μία από 250ms και πάνω.

Ξέρω για αυτή την απογοήτευση που νιωθεις, χαχαχαααα! Όλοι την έχουμε νιώσει αλλά είναι απλά θέμα λογικής.

selectronic
04-04-17, 08:31
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(readVcc);
delay(100);


Αυτό στο κάνει γιατί πριν εμφανίσεις την τιμή για 100ms(!), "καθαριζεις" πρώτα την προηγούμενη με μία lcd.clear();

Βάλε αυτή την εντολή ακριβώς μετά την lcd.print(readVcc);
... έτσι ώστε ακόμα και να αλλάζουν τα δεκαδικά ψηφία να σου καθαρίζει την ουρά.

Επίσης η delay(100) νομίζω είναι πολύ λίγη, θα σου αλλάζει πολύ γρήγορα τιμές. Βάλε μία από 250ms και πάνω.

Ξέρω για αυτή την απογοήτευση που νιωθεις, χαχαχαααα! Όλοι την έχουμε νιώσει αλλά είναι απλά θέμα λογικής.

Αν κατάλαβα καλά, λες να μην γράφω κενά πριν κάθε τιμή που γράφω στην LCD αλλά αντί αυτού να κάνω παύση Xms στο τέλος και αμέσως μετά να καθαρίζω την LCD με lcd.clear(), που μου ακούγεται πολύ πιο έξυπνο από αυτό που έκανα εγώ!
Για αρχή ο κώδικας που τεστάρω δεν είναι μόνο το κομμάτι που έβαλα, μετράω δύο AnalogRead και τυπώνω διάφορα στην οθόνη. Δεν τον έβαλα όλον γιατί δεν υπάρχει λόγος να βάζω ανθρώπους να διαβάζουν 50 άσχετες γραμμές εφόσον το πρόβλημα είναι σε ένα μέρος του κώδικα ή τουλάχιστον το πρόβλημα παραμένει με ή χωρίς τις εξτρά μετρήσεις που κάνω.

Σε μία δοκιμή στα γρήγορα που έκανα, έσβησα τον κώδικα που έγραφε κενά πριν τις 7 τιμές που τυπώνω στην οθόνη και έβαλα "delay(500); lcd.clear();" στο τέλος αντί του συνόλου (220) που είχα διάσπαρτο στον κώδικα, αλλά είχα το αντίθετο αποτέλεσμα: πριν δεν είχε καθόλου flicker και πιο γρήγορη απόκριση στις αλλαγές τάσης (το τελευταίο εννοείτε), αλλά με το ίδιο ή μέχρι και (500) delay και clear στο τέλος χειροτέρεψε η κατάσταση και στα δύο (flicker και απόκριση). Δεν ξέρω γιατί και θα το δουλέψω κι άλλο, σίγουρα ο δικός τρόπος είναι πιο σωστός απο τον μπακαλίστικο τον δικό μου, απλά δεν τον είχα σκεφτεί XD

Πάντως στο παράδειγμα που έχεις βάλεις quote, πρώτα γράφει την readVcc και μετά κάνει παύση, άρα η τιμή μένει για 100ms τυπωμένη στην LCD, πριν κάνει loop το πρόγραμμα και πάει στα κενά, σωστά?



Τελικά μάλλον θα μετράω και την Vcc συνέχεια, δηλαδή την έβαλα στο loop, αλλά ξέρεις τι έκανα λάθος πριν και όταν έβαζα το κομμάτι της μέτρησης στο setup και το κομμάτι που μόνο τυπώνει στην LCD + το delay, δεν έκανε καν compile και έβγαζε μήνυμα στο IDE "δεν μου έχεις πει τι είναι 'readVcc' !" ???

Βάλω όλον το κώδικα παρακάτω, που δουλεύει 100% τώρα και μετράει την Vcc που αλλάζει από USB power σε εξωτερική 12V στο 'Vin', αλλά μετράει "καλά" και στις δύο περιπτώσεις τισ δύο αναλογικές εισόδους, απλώς θέλει λίγο καλιμπράρισμα ακόμα για να μετράει όσο καλύτερα γίνεται:



#include <LiquidCrystal.h>


LiquidCrystal lcd(2, 4, 6, 7, 8, 9);
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;

void setup()
{

lcd.begin(20, 2);


}

void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);

long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL; readVcc |= ADCH<<8; readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV

float VccReal = (float) readVcc / 1000;

lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(VccReal,2);

// Measure multiple times the Analog Pin and make an 'Average':
//
// Take multiple measurements of the same AnalogInput
int rawADC0 = analogRead (Read1);
int rawADC1 = analogRead (Read1);
int rawADC2 = analogRead (Read1);
int rawADC3 = analogRead (Read1);
int rawADC4 = analogRead (Read1);
int rawADC5 = analogRead (Read1);
int rawADC6 = analogRead (Read1);
int rawADC7 = analogRead (Read1);
int rawADC8 = analogRead (Read1);
int rawADC9 = analogRead (Read1);
int rawADC10 = analogRead (Read1);
int rawADC11 = analogRead (Read1);
int rawADC12 = analogRead (Read1);
int rawADC13 = analogRead (Read1);
int rawADC14 = analogRead (Read1);
int rawADC15 = analogRead (Read1);
int rawADC16 = analogRead (Read1);
int rawADC17 = analogRead (Read1);
int rawADC18 = analogRead (Read1);
int rawADC19 = analogRead (Read1);
// Make first average of those values
int average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
// Make the 'int' average value into a 'float', calc 1/1000 of that average value and select percent under/over to be "discarded"
float OnePercentADC = (float) average / 1000;
float percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
// From the previous values, exclude those that are 10% more/less than made 'average' value, and re-calculate a new average
float average2 = 0;
int count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {average2 = average2 + rawADC0; count++;}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {average2 = average2 + rawADC1; count++;}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {average2 = average2 + rawADC2; count++;}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {average2 = average2 + rawADC3; count++;}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {average2 = average2 + rawADC4; count++;}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {average2 = average2 + rawADC5; count++;}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {average2 = average2 + rawADC6; count++;}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {average2 = average2 + rawADC7; count++;}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {average2 = average2 + rawADC8; count++;}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {average2 = average2 + rawADC9; count++;}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {average2 = average2 + rawADC10; count++;}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {average2 = average2 + rawADC11; count++;}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {average2 = average2 + rawADC12; count++;}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {average2 = average2 + rawADC13; count++;}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {average2 = average2 + rawADC14; count++;}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {average2 = average2 + rawADC15; count++;}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {average2 = average2 + rawADC16; count++;}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {average2 = average2 + rawADC17; count++;}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {average2 = average2 + rawADC18; count++;}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {average2 = average2 + rawADC19; count++;}
average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;

lcd.setCursor(5, 0);
lcd.print(voltage,3);lcd.print("V");

lcd.setCursor(12, 0);
lcd.print(" ");
lcd.setCursor(12, 0);
lcd.print(average);

lcd.setCursor(17, 0);
lcd.print(" ");
lcd.setCursor(17, 0);
lcd.print(count);

rawADC0 = analogRead (Read2);
rawADC1 = analogRead (Read2);
rawADC2 = analogRead (Read2);
rawADC3 = analogRead (Read2);
rawADC4 = analogRead (Read2);
rawADC5 = analogRead (Read2);
rawADC6 = analogRead (Read2);
rawADC7 = analogRead (Read2);
rawADC8 = analogRead (Read2);
rawADC9 = analogRead (Read2);
rawADC10 = analogRead (Read2);
rawADC11 = analogRead (Read2);
rawADC12 = analogRead (Read2);
rawADC13 = analogRead (Read2);
rawADC14 = analogRead (Read2);
rawADC15 = analogRead (Read2);
rawADC16 = analogRead (Read2);
rawADC17 = analogRead (Read2);
rawADC18 = analogRead (Read2);
rawADC19 = analogRead (Read2);
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {average2 = average2 + rawADC0; count++;}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {average2 = average2 + rawADC1; count++;}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {average2 = average2 + rawADC2; count++;}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {average2 = average2 + rawADC3; count++;}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {average2 = average2 + rawADC4; count++;}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {average2 = average2 + rawADC5; count++;}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {average2 = average2 + rawADC6; count++;}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {average2 = average2 + rawADC7; count++;}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {average2 = average2 + rawADC8; count++;}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {average2 = average2 + rawADC9; count++;}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {average2 = average2 + rawADC10; count++;}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {average2 = average2 + rawADC11; count++;}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {average2 = average2 + rawADC12; count++;}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {average2 = average2 + rawADC13; count++;}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {average2 = average2 + rawADC14; count++;}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {average2 = average2 + rawADC15; count++;}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {average2 = average2 + rawADC16; count++;}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {average2 = average2 + rawADC17; count++;}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {average2 = average2 + rawADC18; count++;}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {average2 = average2 + rawADC19; count++;}
average = average2 / count;
float voltage2 = ((float) average + CalibV ) / 1024.0 * VccReal;

lcd.setCursor(5, 1);
lcd.print(voltage2,3);lcd.print("V");

lcd.setCursor(12, 1);
lcd.print(" ");
lcd.setCursor(12, 1);
lcd.print(average);

lcd.setCursor(17, 1);
lcd.print(" ");
lcd.setCursor(17, 1);
lcd.print(count);


// a small Delay is needed, else the LCD flickers too quickly, its annoying...
delay(200);


}


Στην LCD μου δείχνει αυτό:

http://i.imgur.com/Ra6UN8Q.jpg

manolena
04-04-17, 09:24
Κάποιες διορθώσεις θέλω να κάνω με βάση και τη φωτογραφία που ανέβασες.

Είναι λογικό έτσι όπως σου το είπα να κάνει flickering γιατί ακριβώς μετά την τιμή που παρουσιάζεις στην οθόνη (float με 3 δεκαδικά) βάζεις και την lcd.print(" ") με 5 κενα και σου σβήνει τα επόμενα characters.
Με βάση λοιπόν αυτό που βλέπω στη φωτογραφία:

Στη θέση lcd.setCursor(0,1);(δεύτερη γραμμή, πρώτο χαρακτήρα) εμφανίζεις με εύρος 2 δεκαδικών την float VccReal. Άρα το κομμάτι:


lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(VccReal,2);
...θα γίνει:


lcd.setCursor(0, 1);
lcd.print(VccReal,2)
delay(100);
Θα υπάρχει αλλαγή της τιμής χωρίς να σβήνεται με κενά η προηγούμενη, πράγμα που θα προκαλούσε το flickering που βλέπεις. Αρκεί να παρουσιάζεις πάντα το ίδιο μήκος της μεταβλητής (1 ακέραιο ψηφίο, υποδιαστολή και 2 δεκαδικά).

Πιο κάτω τώρα, εκεί που λες:


average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;

lcd.setCursor(5, 0);
lcd.print(voltage,3);lcd.print("V");

lcd.setCursor(12, 0);
lcd.print(" ");
lcd.setCursor(12, 0);
lcd.print(average);

lcd.setCursor(17, 0);
lcd.print(" ");
lcd.setCursor(17, 0);
lcd.print(count);


...θα το κάνεις:



average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;

lcd.setCursor(5, 0);
lcd.print(voltage,3);
lcd.print("V");

lcd.setCursor(12, 0);
lcd.print(average);

lcd.setCursor(17, 0);
lcd.print(count);


Δοκίμασε και πες μας.

selectronic
04-04-17, 09:33
Αντί να πηγαίνω προς καλό, όλο και χειρότερα τα κάνω :lool:

Από την αρχή ολες μου τις δοκιμές τις έκανα με την πράσινη 20x2 LCD (χωρίς backlight), γιατί είναι χύμα στο κύμα τα καλώδια παντού και έλεγα αν κάνω βλακεία και κάψω Arduino και LCD, να είναι τουλάχιστον η πράσινη που είναι μόνο για τεστ (το πλάνο ήταν πάντα να μπει η μπλε).
Λέω τώρα που δοκίμαζα τα lcd.clear κτλ, κάτσε να βάλω την μπλε, να δω μήπως θα είναι ΟΚ με αυτή, μην παιδεύομαι άδικα με την προσωρινή... Ε με την μπλε δείχνει αίσχος, εκεί που το έβλεπες το flicker στην πράσινη αλλά δεν ήταν τίποτα τρομερό στο μάτι, στην μπλε δείχνει τελείως χάλια: όταν σβήνουν τα γράμματα (στο clear/κενά) σκουραίνει πολύ το σημείο εκείνο και είναι περίπου 256% χειρότερο από την άλλη lol.
To αν θα είναι με κενά ή clear στο τέλος δεν αλλάζει και πολλά, ούτε και το μέγεθος της καθυστέρησης το οποίο απλώς αλλάζει την συχνότητα με την οποία αναβοσβήνει η LCD... :angry:

Αντί να πηγαίνω προς το τέλος της "κατασκευής", ανοίγω και άλλα θέματα...

Τι να κάνουμε, αγαθά κόποις κτώνται...

manolena
04-04-17, 09:34
Τώρα που σου κάνει αυτά, βάλε τον κώδικα εδώ να τον διορθώσουμε on the fly.

selectronic
04-04-17, 09:44
Έβαλα τώρα στην 16x2 μπλε, delays στα 3-4 σημεία που τυπώνω τιμές και ένα clear στο τέλος, και τώρα το αναβόσβημα έγινε σαν κύμα κάπως (φυσικό με τα delay "σε σειρά")...

Βάζω τον κώδικα, που το μόνο που άλλαξε είναι ότι έβγαλα τα "count" γιατί δεν χωράνε στην 16x2, αφού προσφέρεσαι να βοηθήσεις. :)
Πάντως αυτό που θα έκανα αν δεν έλεγες να το κάνουμε live, είναι να το παλέψω λίγο μόνος, και να δω αν θα μπορέσω να το λύσω με πειραματισμούς σε μέθοδο/τιμές πριν ξαναποστάρω πχ αύριο....
Δεν λέω όμως και όχι στην βοήθεια, να είσαι καλά!



#include <LiquidCrystal.h>


// LiquidCrystal lcd(2, 4, 6, 7, 8, 9);
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;



void setup()
{

lcd.begin(16, 2);




}

void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);

long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL; readVcc |= ADCH<<8; readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV

float VccReal = (float) readVcc / 1000;

lcd.setCursor(0, 1);
lcd.print(VccReal,2);
delay(100);

// Measure multiple times the Analog Pin and make an 'Average':
//
// Take multiple measurements of the same AnalogInput
int rawADC0 = analogRead (Read1);
int rawADC1 = analogRead (Read1);
int rawADC2 = analogRead (Read1);
int rawADC3 = analogRead (Read1);
int rawADC4 = analogRead (Read1);
int rawADC5 = analogRead (Read1);
int rawADC6 = analogRead (Read1);
int rawADC7 = analogRead (Read1);
int rawADC8 = analogRead (Read1);
int rawADC9 = analogRead (Read1);
int rawADC10 = analogRead (Read1);
int rawADC11 = analogRead (Read1);
int rawADC12 = analogRead (Read1);
int rawADC13 = analogRead (Read1);
int rawADC14 = analogRead (Read1);
int rawADC15 = analogRead (Read1);
int rawADC16 = analogRead (Read1);
int rawADC17 = analogRead (Read1);
int rawADC18 = analogRead (Read1);
int rawADC19 = analogRead (Read1);
// Make first average of those values
int average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
// Make the 'int' average value into a 'float', calc 1/1000 of that average value and select percent under/over to be "discarded"
float OnePercentADC = (float) average / 1000;
float percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
// From the previous values, exclude those that are 10% more/less than made 'average' value, and re-calculate a new average
float average2 = 0;
int count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {average2 = average2 + rawADC0; count++;}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {average2 = average2 + rawADC1; count++;}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {average2 = average2 + rawADC2; count++;}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {average2 = average2 + rawADC3; count++;}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {average2 = average2 + rawADC4; count++;}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {average2 = average2 + rawADC5; count++;}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {average2 = average2 + rawADC6; count++;}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {average2 = average2 + rawADC7; count++;}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {average2 = average2 + rawADC8; count++;}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {average2 = average2 + rawADC9; count++;}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {average2 = average2 + rawADC10; count++;}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {average2 = average2 + rawADC11; count++;}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {average2 = average2 + rawADC12; count++;}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {average2 = average2 + rawADC13; count++;}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {average2 = average2 + rawADC14; count++;}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {average2 = average2 + rawADC15; count++;}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {average2 = average2 + rawADC16; count++;}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {average2 = average2 + rawADC17; count++;}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {average2 = average2 + rawADC18; count++;}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {average2 = average2 + rawADC19; count++;}
average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;

lcd.setCursor(5, 0);
lcd.print(voltage,3);lcd.print("V");
delay(100);

lcd.setCursor(12, 0);
lcd.print(average);
delay(100);

// lcd.setCursor(17, 0);
// lcd.print(" ");
// lcd.setCursor(17, 0);
// lcd.print(count);

rawADC0 = analogRead (Read2);
rawADC1 = analogRead (Read2);
rawADC2 = analogRead (Read2);
rawADC3 = analogRead (Read2);
rawADC4 = analogRead (Read2);
rawADC5 = analogRead (Read2);
rawADC6 = analogRead (Read2);
rawADC7 = analogRead (Read2);
rawADC8 = analogRead (Read2);
rawADC9 = analogRead (Read2);
rawADC10 = analogRead (Read2);
rawADC11 = analogRead (Read2);
rawADC12 = analogRead (Read2);
rawADC13 = analogRead (Read2);
rawADC14 = analogRead (Read2);
rawADC15 = analogRead (Read2);
rawADC16 = analogRead (Read2);
rawADC17 = analogRead (Read2);
rawADC18 = analogRead (Read2);
rawADC19 = analogRead (Read2);
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {average2 = average2 + rawADC0; count++;}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {average2 = average2 + rawADC1; count++;}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {average2 = average2 + rawADC2; count++;}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {average2 = average2 + rawADC3; count++;}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {average2 = average2 + rawADC4; count++;}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {average2 = average2 + rawADC5; count++;}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {average2 = average2 + rawADC6; count++;}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {average2 = average2 + rawADC7; count++;}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {average2 = average2 + rawADC8; count++;}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {average2 = average2 + rawADC9; count++;}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {average2 = average2 + rawADC10; count++;}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {average2 = average2 + rawADC11; count++;}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {average2 = average2 + rawADC12; count++;}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {average2 = average2 + rawADC13; count++;}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {average2 = average2 + rawADC14; count++;}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {average2 = average2 + rawADC15; count++;}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {average2 = average2 + rawADC16; count++;}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {average2 = average2 + rawADC17; count++;}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {average2 = average2 + rawADC18; count++;}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {average2 = average2 + rawADC19; count++;}
average = average2 / count;
float voltage2 = ((float) average + CalibV ) / 1024.0 * VccReal;

lcd.setCursor(5, 1);
lcd.print(voltage2,3);lcd.print("V");
delay(100);

lcd.setCursor(12, 1);
lcd.print(average);
delay(100);

// lcd.setCursor(17, 1);
// lcd.print(" ");
// lcd.setCursor(17, 1);
// lcd.print(count);


// delay(200);
lcd.clear();


}

selectronic
04-04-17, 09:46
Καλύτερα είναι με μόνο ένα delay+clear στο τέλος όπως είχες πει και το καλύτερο (αλλά όχι σε καμία περίπτωση "καλό") delay είναι στα ~200...
Δεν έχω και κάμερα καλή να ανεβάσω τι κάνει :/

manolena
04-04-17, 09:48
Να ρωτήσω, μέχρι τι τάσεις προβλέπεται να μετράς; Εννοώ πόσο μήκος (0-30 με 3 δεκαδικά πχ). Σε όλα τα πεδία αν γίνεται γράψε για κάθε μια το εύρος.

selectronic
04-04-17, 09:51
2 δεκαδικά είναι τέλεια, και έτσι και αλλιώς με τις 1024 τιμές υπάρχουν "στάνταρ" τιμές που τυπώνει, πχ 27.5mV -επόμενη-> 28.5mV -επόμενη-> 29.6mV κτλ
EDIT: 0-50V και 0-10Α τα σίγουρα, και πιθανότατα τριψήφια Watt και μία θερμοκρασία σε δύο ψηφία.

Δεν θα είναι στο τέλος 100% όπως τώρα έτσι, δεν θα τυπώνω την raw ADC value και timer, 4 τιμές μόνο στις τέσσερις γωνίες (κάπως) της LCD, όπως το φαντάζομαι....

selectronic
04-04-17, 10:03
Βίντεο, δυστυχώς άθλιας ποιότητας:

Με τον κώδικα που έβαλα στο #57 με τα πολλά και μοιρασμένα delays:


https://www.youtube.com/watch?v=ia2P06bLCnA&amp;feature=youtu.be

manolena
04-04-17, 10:03
Στο συμμάζεψα λίγο, κάνε μια δοκιμή με 20x2 οθόνη:



#include <LiquidCrystal.h>


//================================================== =================
// LiquidCrystal lcd(2, 4, 6, 7, 8, 9);
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;
long readVcc;
float OnePercentADC, percentADC;
float VccReal = (float) readVcc / 1000;
int rawADC0, rawADC1, rawADC2, rawADC3, rawADC4, rawADC5, rawADC6,
rawADC7, rawADC8, rawADC9, rawADC10, rawADC11, rawADC12, rawADC13,
rawADC14, rawADC15, rawADC16, rawADC17, rawADC18, rawADC19 = 0;
int average;
float average2 = 0;
int count = 0;
//================================================== =================
void setup()
{
lcd.begin(16, 2);// lcd.begin(20, 2);
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);




ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV


lcd.setCursor(0, 1);
lcd.print(VccReal,2);


measureVoltageAverage();
measureVoltage_1_Average();
delay(200);


}
//================================================== =================
void measureVoltageAverage()
{
// Measure multiple times the Analog Pin and make an 'Average':
//
// Take multiple measurements of the same AnalogInput
rawADC0 = analogRead (Read1);
rawADC1 = analogRead (Read1);
rawADC2 = analogRead (Read1);
rawADC3 = analogRead (Read1);
rawADC4 = analogRead (Read1);
rawADC5 = analogRead (Read1);
rawADC6 = analogRead (Read1);
rawADC7 = analogRead (Read1);
rawADC8 = analogRead (Read1);
rawADC9 = analogRead (Read1);
rawADC10 = analogRead (Read1);
rawADC11 = analogRead (Read1);
rawADC12 = analogRead (Read1);
rawADC13 = analogRead (Read1);
rawADC14 = analogRead (Read1);
rawADC15 = analogRead (Read1);
rawADC16 = analogRead (Read1);
rawADC17 = analogRead (Read1);
rawADC18 = analogRead (Read1);
rawADC19 = analogRead (Read1);
// Make first average of those values
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
// Make the 'int' average value into a 'float', calc 1/1000 of that average value and select percent under/over to be "discarded"
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
// From the previous values, exclude those that are 10% more/less than made 'average' value, and re-calculate a new average
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {
average2 = average2 + rawADC0;
count++;
}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {
average2 = average2 + rawADC1;
count++;
}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {
average2 = average2 + rawADC2;
count++;
}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {
average2 = average2 + rawADC3;
count++;
}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {
average2 = average2 + rawADC4;
count++;
}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {
average2 = average2 + rawADC5;
count++;
}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {
average2 = average2 + rawADC6;
count++;
}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {
average2 = average2 + rawADC7;
count++;
}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {
average2 = average2 + rawADC8;
count++;
}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {
average2 = average2 + rawADC9;
count++;
}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {
average2 = average2 + rawADC10;
count++;
}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {
average2 = average2 + rawADC11;
count++;
}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {
average2 = average2 + rawADC12;
count++;
}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {
average2 = average2 + rawADC13;
count++;
}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {
average2 = average2 + rawADC14;
count++;
}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {
average2 = average2 + rawADC15;
count++;
}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {
average2 = average2 + rawADC16;
count++;
}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {
average2 = average2 + rawADC17;
count++;
}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {
average2 = average2 + rawADC18;
count++;
}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {
average2 = average2 + rawADC19;
count++;
}
average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;


lcd.setCursor(5, 0);
lcd.print(voltage,3);
lcd.print("V");


lcd.setCursor(12, 0);
lcd.print(average);


// lcd.setCursor(17, 0);
// lcd.print(" ");
// lcd.setCursor(17, 0);
// lcd.print(count);
}
//================================================== =================
void measureVoltage_1_Average()
{
rawADC0 = analogRead (Read2);
rawADC1 = analogRead (Read2);
rawADC2 = analogRead (Read2);
rawADC3 = analogRead (Read2);
rawADC4 = analogRead (Read2);
rawADC5 = analogRead (Read2);
rawADC6 = analogRead (Read2);
rawADC7 = analogRead (Read2);
rawADC8 = analogRead (Read2);
rawADC9 = analogRead (Read2);
rawADC10 = analogRead (Read2);
rawADC11 = analogRead (Read2);
rawADC12 = analogRead (Read2);
rawADC13 = analogRead (Read2);
rawADC14 = analogRead (Read2);
rawADC15 = analogRead (Read2);
rawADC16 = analogRead (Read2);
rawADC17 = analogRead (Read2);
rawADC18 = analogRead (Read2);
rawADC19 = analogRead (Read2);
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {
average2 = average2 + rawADC0;
count++;
}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {
average2 = average2 + rawADC1;
count++;
}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {
average2 = average2 + rawADC2;
count++;
}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {
average2 = average2 + rawADC3;
count++;
}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {
average2 = average2 + rawADC4;
count++;
}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {
average2 = average2 + rawADC5;
count++;
}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {
average2 = average2 + rawADC6;
count++;
}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {
average2 = average2 + rawADC7;
count++;
}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {
average2 = average2 + rawADC8;
count++;
}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {
average2 = average2 + rawADC9;
count++;
}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {
average2 = average2 + rawADC10;
count++;
}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {
average2 = average2 + rawADC11;
count++;
}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {
average2 = average2 + rawADC12;
count++;
}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {
average2 = average2 + rawADC13;
count++;
}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {
average2 = average2 + rawADC14;
count++;
}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {
average2 = average2 + rawADC15;
count++;
}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {
average2 = average2 + rawADC16;
count++;
}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {
average2 = average2 + rawADC17;
count++;
}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {
average2 = average2 + rawADC18;
count++;
}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {
average2 = average2 + rawADC19;
count++;
}
average = average2 / count;
float voltage2 = ((float) average + CalibV ) / 1024.0 * VccReal;


lcd.setCursor(5, 1);
lcd.print(voltage2,3);
lcd.print("V");


lcd.setCursor(12, 1);
lcd.print(average);


// lcd.setCursor(17, 1);
// lcd.print(" ");
// lcd.setCursor(17, 1);
// lcd.print(count);




// delay(200);
// lcd.clear();
}
//================================================== =================
//================================================== =================
//================================================== =================
//================================================== =================

selectronic
04-04-17, 10:04
Με ένα μόνο delay(200) στο τέλος και καπάκι lcd.clear() }


https://youtu.be/NXbCUYbN9GI

manolena
04-04-17, 10:05
Βίντεο, δυστυχώς άθλιας ποιότητας:

Με τον κώδικα που έβαλα στο #57 με τα πολλά και μοιρασμένα delays:


https://www.youtube.com/watch?v=ia2P06bLCnA&amp;feature=youtu.be

Έλα, αυτό στο κάνει γιατί στο τέλος κάτω κάτω έχεις βάλει να σου σβήνει όλη την οθόνη με lcd.clear(); Κάντην σχόλιο με //
Αν δείς παραπάνω στον κώδικα που έστειλα την έχω κάνει σχόλιο.

selectronic
04-04-17, 10:10
Στο συμμάζεψα λίγο, κάνε μια δοκιμή με 20x2 οθόνη:



#include <LiquidCrystal.h>


//================================================== =================
// LiquidCrystal lcd(2, 4, 6, 7, 8, 9);
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;
long readVcc;
float OnePercentADC, percentADC;
float VccReal = (float) readVcc / 1000;
int rawADC0, rawADC1, rawADC2, rawADC3, rawADC4, rawADC5, rawADC6,
rawADC7, rawADC8, rawADC9, rawADC10, rawADC11, rawADC12, rawADC13,
rawADC14, rawADC15, rawADC16, rawADC17, rawADC18, rawADC19 = 0;
int average;
float average2 = 0;
int count = 0;
//================================================== =================
void setup()
{
lcd.begin(16, 2);// lcd.begin(20, 2);
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);




ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV


lcd.setCursor(0, 1);
lcd.print(VccReal,2);


measureVoltageAverage();
measureVoltage_1_Average();
delay(200);


}
//================================================== =================
void measureVoltageAverage()
{
// Measure multiple times the Analog Pin and make an 'Average':
//
// Take multiple measurements of the same AnalogInput
rawADC0 = analogRead (Read1);
rawADC1 = analogRead (Read1);
rawADC2 = analogRead (Read1);
rawADC3 = analogRead (Read1);
rawADC4 = analogRead (Read1);
rawADC5 = analogRead (Read1);
rawADC6 = analogRead (Read1);
rawADC7 = analogRead (Read1);
rawADC8 = analogRead (Read1);
rawADC9 = analogRead (Read1);
rawADC10 = analogRead (Read1);
rawADC11 = analogRead (Read1);
rawADC12 = analogRead (Read1);
rawADC13 = analogRead (Read1);
rawADC14 = analogRead (Read1);
rawADC15 = analogRead (Read1);
rawADC16 = analogRead (Read1);
rawADC17 = analogRead (Read1);
rawADC18 = analogRead (Read1);
rawADC19 = analogRead (Read1);
// Make first average of those values
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
// Make the 'int' average value into a 'float', calc 1/1000 of that average value and select percent under/over to be "discarded"
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
// From the previous values, exclude those that are 10% more/less than made 'average' value, and re-calculate a new average
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {
average2 = average2 + rawADC0;
count++;
}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {
average2 = average2 + rawADC1;
count++;
}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {
average2 = average2 + rawADC2;
count++;
}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {
average2 = average2 + rawADC3;
count++;
}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {
average2 = average2 + rawADC4;
count++;
}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {
average2 = average2 + rawADC5;
count++;
}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {
average2 = average2 + rawADC6;
count++;
}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {
average2 = average2 + rawADC7;
count++;
}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {
average2 = average2 + rawADC8;
count++;
}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {
average2 = average2 + rawADC9;
count++;
}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {
average2 = average2 + rawADC10;
count++;
}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {
average2 = average2 + rawADC11;
count++;
}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {
average2 = average2 + rawADC12;
count++;
}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {
average2 = average2 + rawADC13;
count++;
}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {
average2 = average2 + rawADC14;
count++;
}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {
average2 = average2 + rawADC15;
count++;
}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {
average2 = average2 + rawADC16;
count++;
}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {
average2 = average2 + rawADC17;
count++;
}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {
average2 = average2 + rawADC18;
count++;
}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {
average2 = average2 + rawADC19;
count++;
}
average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;


lcd.setCursor(5, 0);
lcd.print(voltage,3);
lcd.print("V");


lcd.setCursor(12, 0);
lcd.print(average);


// lcd.setCursor(17, 0);
// lcd.print(" ");
// lcd.setCursor(17, 0);
// lcd.print(count);
}
//================================================== =================
void measureVoltage_1_Average()
{
rawADC0 = analogRead (Read2);
rawADC1 = analogRead (Read2);
rawADC2 = analogRead (Read2);
rawADC3 = analogRead (Read2);
rawADC4 = analogRead (Read2);
rawADC5 = analogRead (Read2);
rawADC6 = analogRead (Read2);
rawADC7 = analogRead (Read2);
rawADC8 = analogRead (Read2);
rawADC9 = analogRead (Read2);
rawADC10 = analogRead (Read2);
rawADC11 = analogRead (Read2);
rawADC12 = analogRead (Read2);
rawADC13 = analogRead (Read2);
rawADC14 = analogRead (Read2);
rawADC15 = analogRead (Read2);
rawADC16 = analogRead (Read2);
rawADC17 = analogRead (Read2);
rawADC18 = analogRead (Read2);
rawADC19 = analogRead (Read2);
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {
average2 = average2 + rawADC0;
count++;
}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {
average2 = average2 + rawADC1;
count++;
}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {
average2 = average2 + rawADC2;
count++;
}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {
average2 = average2 + rawADC3;
count++;
}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {
average2 = average2 + rawADC4;
count++;
}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {
average2 = average2 + rawADC5;
count++;
}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {
average2 = average2 + rawADC6;
count++;
}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {
average2 = average2 + rawADC7;
count++;
}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {
average2 = average2 + rawADC8;
count++;
}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {
average2 = average2 + rawADC9;
count++;
}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {
average2 = average2 + rawADC10;
count++;
}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {
average2 = average2 + rawADC11;
count++;
}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {
average2 = average2 + rawADC12;
count++;
}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {
average2 = average2 + rawADC13;
count++;
}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {
average2 = average2 + rawADC14;
count++;
}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {
average2 = average2 + rawADC15;
count++;
}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {
average2 = average2 + rawADC16;
count++;
}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {
average2 = average2 + rawADC17;
count++;
}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {
average2 = average2 + rawADC18;
count++;
}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {
average2 = average2 + rawADC19;
count++;
}
average = average2 / count;
float voltage2 = ((float) average + CalibV ) / 1024.0 * VccReal;


lcd.setCursor(5, 1);
lcd.print(voltage2,3);
lcd.print("V");


lcd.setCursor(12, 1);
lcd.print(average);


// lcd.setCursor(17, 1);
// lcd.print(" ");
// lcd.setCursor(17, 1);
// lcd.print(count);




// delay(200);
// lcd.clear();
}
//================================================== =================
//================================================== =================
//================================================== =================
//================================================== =================








Νομίζω μόλις τον έψησα αυτόν που είναι στην πράσινη όταν σκούντησα το καλωδιομάνι για να βάλω την κάμερα να πάρω βίντεο XD
Πρόλαβε και μέτρησε (αργά ή μου φάνηκε?) μέχρι το 8 στον timer πάντως, δούλεψε...

Fire Doger
04-04-17, 10:18
Χμμμ με τις επαναλήψεις δεν τα πας πολύ καλά ε? :P

Οι πρώτες 20 γραμμές:
int rawADC[20];
for(byte i =0; i<20; i ++)
rawADC[i] = analogRead (Read1);

Οι επόμενες 20 γραμμές
for(byte i=0; i<20; i++)
if (rawADC[i] <= average+percentADC && rawADC[i] >= average-percentADC) {
average2 = average2 + rawADC[i];
count++;
}

Παραπάνω αντί να έχω 20 μεταβλητές με 20 ονόματα έχω ένα πίνακα με 20 θέσεις και κάθε θέση είναι 1 μεταβλητή. Άρα με το ίδιο όνομα αλλάζοντας την θέση μέσω της επανάληψης αλλάζει και η μεταβλητή στην οποία αναφέρομαι. Τα υπόλοιπα παραμένουν ίδια.
Το ίδιο μπορεί να επαναληφθεί και για τις επόμενες 40 γραμμές.
Δηλαδή στις 200 μετρήσεις τι θα έκανες? :P
Αν σε βολεύει το κρατάς, το ίδιο πράγμα είναι σχεδόν.

Edit: και για το average:
int average =0;
for(byte i=0; i<20; i++){
average+=rawADC[i];
}
average = average/20;

**Μου είχε ξεφύγει κάτι πριν το edit

selectronic
04-04-17, 10:21
Ναι, δεν σαλεύει η πράσινη (ο πράσινος?). Έλεγα μήπως πέρασα το "LiquidCrystal lcd(2, 8, 4, 5, 6, 7);" που είναι της μπλε LCD, γιατί είμαι και μαζοχιστής και δεν έβαλα τα ίδια πιν, αλλά όχι...
Meh, κίνδυνοι του επαγγέλματος είναι αυτοί lol.

Τριπλο-τσεκάρω και δοκιμάζω μπλε, και θα ξανα-ανεβάσω τον κώδικα γιατί δεν είχα καταλάβει ότι είχα αφήσει και τα δύο "LiquidCrystal lcd(.........);" μέσα.

selectronic
04-04-17, 10:24
Χμμμ με τις επαναλήψεις δεν τα πας πολύ καλά ε? :P

Οι πρώτες 20 γραμμές:
int rawADC[20];
for(byte i =0; i<20; i ++)
rawADC[i] = analogRead (Read1);

Οι επόμενες 20 γραμμές
for(byte i=0; i<20; i++)
if (rawADC[i] <= average+percentADC && rawADC[i] >= average-percentADC) {
average2 = average2 + rawADC0;
count++;
}

Παραπάνω αντί να έχω 20 μεταβλητές με 20 ονόματα έχω ένα πίνακα με 20 θέσεις και κάθε θέση είναι 1 μεταβλητή. Άρα με το ίδιο όνομα αλλάζοντας την θέση μέσω της επανάληψης αλλάζει και η μεταβλητή στην οποία αναφέρομαι. Τα υπόλοιπα παραμένουν ίδια.
Το ίδιο μπορεί να επαναληφθεί και για τις επόμενες 40 γραμμές.
Δηλαδή στις 200 μετρήσεις τι θα έκανες? :P
Αν σε βολεύει το κρατάς, το ίδιο πράγμα είναι σχεδόν.

Χα! Το ήξερα ότι σίγουρα υπήρχε τέτοιος τρόπος (for 20, do that shit) αλλά δεν ήξερα πως να το κάνω, και όταν έκανα το κομμάτι με τις 20 επαναλήψεις copy-paste από όπου το βρήκα, δεν είχα κάτσει να βρω καλύτερο τρόπο...
Thanks!

selectronic
04-04-17, 10:34
Τέλειο !!!

Καθόλου, μα ΚΑΘΟΛΟΥ flicker στην 16x2 μπλε! :)
Άσε μου 5 λεπτά να δω τι μαγεία έκανες στον κώδικα...



#include <LiquidCrystal.h>


//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;
long readVcc;
float OnePercentADC, percentADC;
float VccReal = (float) readVcc / 1000;
int rawADC0, rawADC1, rawADC2, rawADC3, rawADC4, rawADC5, rawADC6,
rawADC7, rawADC8, rawADC9, rawADC10, rawADC11, rawADC12, rawADC13,
rawADC14, rawADC15, rawADC16, rawADC17, rawADC18, rawADC19 = 0;
int average;
float average2 = 0;
int count = 0;
//================================================== =================
void setup()
{
lcd.begin(16, 2);//
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);




ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV


lcd.setCursor(0, 1);
lcd.print(VccReal,2);


measureVoltageAverage();
measureVoltage_1_Average();
delay(200);


}
//================================================== =================
void measureVoltageAverage()
{
// Measure multiple times the Analog Pin and make an 'Average':
//
// Take multiple measurements of the same AnalogInput
rawADC0 = analogRead (Read1);
rawADC1 = analogRead (Read1);
rawADC2 = analogRead (Read1);
rawADC3 = analogRead (Read1);
rawADC4 = analogRead (Read1);
rawADC5 = analogRead (Read1);
rawADC6 = analogRead (Read1);
rawADC7 = analogRead (Read1);
rawADC8 = analogRead (Read1);
rawADC9 = analogRead (Read1);
rawADC10 = analogRead (Read1);
rawADC11 = analogRead (Read1);
rawADC12 = analogRead (Read1);
rawADC13 = analogRead (Read1);
rawADC14 = analogRead (Read1);
rawADC15 = analogRead (Read1);
rawADC16 = analogRead (Read1);
rawADC17 = analogRead (Read1);
rawADC18 = analogRead (Read1);
rawADC19 = analogRead (Read1);
// Make first average of those values
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
// Make the 'int' average value into a 'float', calc 1/1000 of that average value and select percent under/over to be "discarded"
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
// From the previous values, exclude those that are 10% more/less than made 'average' value, and re-calculate a new average
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {
average2 = average2 + rawADC0;
count++;
}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {
average2 = average2 + rawADC1;
count++;
}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {
average2 = average2 + rawADC2;
count++;
}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {
average2 = average2 + rawADC3;
count++;
}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {
average2 = average2 + rawADC4;
count++;
}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {
average2 = average2 + rawADC5;
count++;
}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {
average2 = average2 + rawADC6;
count++;
}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {
average2 = average2 + rawADC7;
count++;
}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {
average2 = average2 + rawADC8;
count++;
}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {
average2 = average2 + rawADC9;
count++;
}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {
average2 = average2 + rawADC10;
count++;
}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {
average2 = average2 + rawADC11;
count++;
}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {
average2 = average2 + rawADC12;
count++;
}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {
average2 = average2 + rawADC13;
count++;
}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {
average2 = average2 + rawADC14;
count++;
}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {
average2 = average2 + rawADC15;
count++;
}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {
average2 = average2 + rawADC16;
count++;
}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {
average2 = average2 + rawADC17;
count++;
}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {
average2 = average2 + rawADC18;
count++;
}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {
average2 = average2 + rawADC19;
count++;
}
average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;


lcd.setCursor(5, 0);
lcd.print(voltage,3);
lcd.print("V");


lcd.setCursor(12, 0);
lcd.print(average);


// lcd.setCursor(17, 0);
// lcd.print(" ");
// lcd.setCursor(17, 0);
// lcd.print(count);
}
//================================================== =================
void measureVoltage_1_Average()
{
rawADC0 = analogRead (Read2);
rawADC1 = analogRead (Read2);
rawADC2 = analogRead (Read2);
rawADC3 = analogRead (Read2);
rawADC4 = analogRead (Read2);
rawADC5 = analogRead (Read2);
rawADC6 = analogRead (Read2);
rawADC7 = analogRead (Read2);
rawADC8 = analogRead (Read2);
rawADC9 = analogRead (Read2);
rawADC10 = analogRead (Read2);
rawADC11 = analogRead (Read2);
rawADC12 = analogRead (Read2);
rawADC13 = analogRead (Read2);
rawADC14 = analogRead (Read2);
rawADC15 = analogRead (Read2);
rawADC16 = analogRead (Read2);
rawADC17 = analogRead (Read2);
rawADC18 = analogRead (Read2);
rawADC19 = analogRead (Read2);
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {
average2 = average2 + rawADC0;
count++;
}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {
average2 = average2 + rawADC1;
count++;
}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {
average2 = average2 + rawADC2;
count++;
}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {
average2 = average2 + rawADC3;
count++;
}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {
average2 = average2 + rawADC4;
count++;
}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {
average2 = average2 + rawADC5;
count++;
}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {
average2 = average2 + rawADC6;
count++;
}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {
average2 = average2 + rawADC7;
count++;
}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {
average2 = average2 + rawADC8;
count++;
}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {
average2 = average2 + rawADC9;
count++;
}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {
average2 = average2 + rawADC10;
count++;
}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {
average2 = average2 + rawADC11;
count++;
}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {
average2 = average2 + rawADC12;
count++;
}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {
average2 = average2 + rawADC13;
count++;
}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {
average2 = average2 + rawADC14;
count++;
}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {
average2 = average2 + rawADC15;
count++;
}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {
average2 = average2 + rawADC16;
count++;
}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {
average2 = average2 + rawADC17;
count++;
}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {
average2 = average2 + rawADC18;
count++;
}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {
average2 = average2 + rawADC19;
count++;
}
average = average2 / count;
float voltage2 = ((float) average + CalibV ) / 1024.0 * VccReal;


lcd.setCursor(5, 1);
lcd.print(voltage2,3);
lcd.print("V");


lcd.setCursor(12, 1);
lcd.print(average);


// lcd.setCursor(17, 1);
// lcd.print(" ");
// lcd.setCursor(17, 1);
// lcd.print(count);




// delay(200);
// lcd.clear();
}
//================================================== =================
//================================================== =================
//================================================== =================
//================================================== =================


Edit: δεν είναι καλή η μέρα αυτή έτσι?
http://i.imgur.com/r5n4MXd.png

selectronic
04-04-17, 10:51
Για κάτσε μία στιγμή, δηλαδή τώρα δεν σβήνει ΠΟΤΕ ότι γράφει? Έτσι έκανα και στα πρώτα βήματα με την LCD, αλλά όταν άλλαζε μία τιμή στην οθόνη σε πιο μεγάλη σε μήκος στην οθόνη και μετά σε μικρότερη πάλι, μέναν τα "εξτρά" ψηφία στην οθόνη: πχ οι τιμές rawADC είναι 1-4 ψηφία. Δεν θα έχω πάλι το ίδιο θέμα αν έχω τιμές που αλλάζουν "μέγεθος" στην LCD (που δεν ξέρω να θα έχω, αλλά ρωτάω για να μαθαίνω!)

Μου έφτιαξες και functions είδα και δεν είναι όλα χύμα μέσα στο loop, θα το μελετήσω πως το έκανες να μάθω. Ήταν στο πρόγραμμα και αυτό να το ψάξω, αλλά ήθελα πρώτα να φτάσω κοντά στο να μου δείχνει πρώτα μία τάση σωστά στην οθόνη και μετά, γιατί πάντα υπήρχε και η περίπτωση να τα πέταγα όλα στον κάδο XD

Τώρα μετράνε τα πάντα πλην του timer/rawADC μηδέν πάντως, αλλά θα το βρω αυτό πιστεύω :)
Το Youtube δεν ξέρω γιατί μουλάρωσε :/

Ευχαριστώ !!!

manolena
04-04-17, 11:02
Για κάτσε μία στιγμή, δηλαδή τώρα δεν σβήνει ΠΟΤΕ ότι γράφει? Έτσι έκανα και στα πρώτα βήματα με την LCD, αλλά όταν άλλαζε μία τιμή στην οθόνη σε πιο μεγάλη σε μήκος στην οθόνη και μετά σε μικρότερη πάλι, μέναν τα "εξτρά" ψηφία στην οθόνη. Δεν θα έχω πάλι το ίδιο θέμα?

Αυτό λύνεται αν προσθέσεις στο τέλος μετά απο την εκτύπωση της μεταβλητής μια εντολή lcd.print(" ") με όσα space-κενά χρειάζεσαι για να σβήνουν τα παραμένοντα ψηφία.
Υπάρχουν και άλλα κόλπα. Αν έχεις υπολογίσει το τελικό μήκος, π.χ. "29.99V", (5 χαρακτήρες με την υποδιαστολή), μπορείς να ορίζεις πάντα την ίδια θέση εκτύπωσης της μεταβλητής, π.χ.
lcd.setCursor(0,1); δεύτερη σειρά πρώτο χαρακτήρα και αν το int κομμάτι της float είναι μικρότερο απο 10 ((int)VccReal < 10) να εμφανίζεις ένα κενό " ", δηλαδή αντί για:



lcd.setCursor(0, 1);
lcd.print(VccReal,2);

...γράφεις:



lcd.setCursor(0, 1);

if((int)VccReal < 10) {
lcd.print(" ");}
lcd.print(VccReal,2);

selectronic
04-04-17, 11:22
...Τώρα μετράνε τα πάντα πλην του timer/rawADC μηδέν πάντως, αλλά θα το βρω αυτό πιστεύω :)...

Με τον τελευταίο: (έκοψα τις δύο functions στην πορεία για να βρω τι τρέχει και μετράει μηδέν και τις τρεις τάσεις)


#include <LiquidCrystal.h>


//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;
long readVcc;
float OnePercentADC, percentADC;
float VccReal = (float) readVcc / 1000;
int rawADC0, rawADC1, rawADC2, rawADC3, rawADC4, rawADC5, rawADC6,
rawADC7, rawADC8, rawADC9, rawADC10, rawADC11, rawADC12, rawADC13,
rawADC14, rawADC15, rawADC16, rawADC17, rawADC18, rawADC19 = 0;
int average;
float average2 = 0;
int count = 0;
//================================================== =================
void setup()
{
lcd.begin(16, 2);//
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);




ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV


lcd.setCursor(0, 1);
lcd.print(VccReal,2);


// measureVoltageAverage();
// measureVoltage_1_Average();
delay(200);


}

Timer μετράει κανονικά, την VccReal την τυπώνει "0.00"

Με το παρακάτω την δείχνει σωστά, πχ "4.62" μέσω USB:


#include <LiquidCrystal.h>


//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;
//
float OnePercentADC, percentADC;
//
int rawADC0, rawADC1, rawADC2, rawADC3, rawADC4, rawADC5, rawADC6,
rawADC7, rawADC8, rawADC9, rawADC10, rawADC11, rawADC12, rawADC13,
rawADC14, rawADC15, rawADC16, rawADC17, rawADC18, rawADC19 = 0;
int average;
float average2 = 0;
int count = 0;
//================================================== =================
void setup()
{
lcd.begin(16, 2);//
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);





long readVcc;

ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV

float VccReal = (float) readVcc / 1000;


lcd.setCursor(0, 1);
lcd.print(VccReal,2);


// measureVoltageAverage();
// measureVoltage_1_Average();
delay(200);


}

EDIT:
Αλλά αν ξαναβάλω και τις functions με τον κώδικά τους μέσα, δεν κάνει compile γιατί δεν δήλωσα την readVcc ή την VccRealμ και αυτό είναι το ίδιο θέμα με το χτεσινό, που αν κούναγα το ίδιο κομμάτι κώδικα από το setup στο loop κτλ, δεν έκανε compile...

Με το τελευταίο +γύρισμα πίσω σε "όλα στο loop", παίζουν όλα (χωρίς flicker). Κάτι με τον κώδικα τον άγριο (C++ ουυυυυυυυυυ) χαλάει την μαγιονέζα όταν δεν τον βάλεις εκεί που πρέπει, με την καλή έννοια...


#include <LiquidCrystal.h>


//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;
//
float OnePercentADC, percentADC;
//
int rawADC0, rawADC1, rawADC2, rawADC3, rawADC4, rawADC5, rawADC6,
rawADC7, rawADC8, rawADC9, rawADC10, rawADC11, rawADC12, rawADC13,
rawADC14, rawADC15, rawADC16, rawADC17, rawADC18, rawADC19 = 0;
int average;
float average2 = 0;
int count = 0;
//================================================== =================
void setup()
{
lcd.begin(16, 2);//
}
//================================================== =================
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);



long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV
float VccReal = (float) readVcc / 1000;


lcd.setCursor(0, 1);
lcd.print(VccReal,2);


// Measure multiple times the Analog Pin and make an 'Average':
//
// Take multiple measurements of the same AnalogInput
int rawADC0 = analogRead (Read1);
int rawADC1 = analogRead (Read1);
int rawADC2 = analogRead (Read1);
int rawADC3 = analogRead (Read1);
int rawADC4 = analogRead (Read1);
int rawADC5 = analogRead (Read1);
int rawADC6 = analogRead (Read1);
int rawADC7 = analogRead (Read1);
int rawADC8 = analogRead (Read1);
int rawADC9 = analogRead (Read1);
int rawADC10 = analogRead (Read1);
int rawADC11 = analogRead (Read1);
int rawADC12 = analogRead (Read1);
int rawADC13 = analogRead (Read1);
int rawADC14 = analogRead (Read1);
int rawADC15 = analogRead (Read1);
int rawADC16 = analogRead (Read1);
int rawADC17 = analogRead (Read1);
int rawADC18 = analogRead (Read1);
int rawADC19 = analogRead (Read1);
// Make first average of those values
int average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
// Make the 'int' average value into a 'float', calc 1/1000 of that average value and select percent under/over to be "discarded"
float OnePercentADC = (float) average / 1000;
float percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
// From the previous values, exclude those that are 10% more/less than made 'average' value, and re-calculate a new average
float average2 = 0;
int count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {average2 = average2 + rawADC0; count++;}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {average2 = average2 + rawADC1; count++;}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {average2 = average2 + rawADC2; count++;}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {average2 = average2 + rawADC3; count++;}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {average2 = average2 + rawADC4; count++;}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {average2 = average2 + rawADC5; count++;}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {average2 = average2 + rawADC6; count++;}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {average2 = average2 + rawADC7; count++;}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {average2 = average2 + rawADC8; count++;}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {average2 = average2 + rawADC9; count++;}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {average2 = average2 + rawADC10; count++;}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {average2 = average2 + rawADC11; count++;}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {average2 = average2 + rawADC12; count++;}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {average2 = average2 + rawADC13; count++;}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {average2 = average2 + rawADC14; count++;}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {average2 = average2 + rawADC15; count++;}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {average2 = average2 + rawADC16; count++;}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {average2 = average2 + rawADC17; count++;}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {average2 = average2 + rawADC18; count++;}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {average2 = average2 + rawADC19; count++;}
average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;
// just a note, in very small values the rate of discarted values is much higher than 'normal':
// 10 or even more values may be dropped under ~200-250mV, but from then on there is hardly any values dropped (maybe 1-2 MAX) !!!
// this can be a sign of noise, since it produced only in very low mV range levels, READ ABOUT 'NOISE REDUCTION' TECHNIQUES !!!

lcd.setCursor(5, 0);
lcd.print(voltage,3);lcd.print("V");

lcd.setCursor(12, 0);
lcd.print(" ");
lcd.setCursor(12, 0);
lcd.print(average);

// lcd.setCursor(17, 0);
// lcd.print(" ");
// lcd.setCursor(17, 0);
// lcd.print(count);

rawADC0 = analogRead (Read2);
rawADC1 = analogRead (Read2);
rawADC2 = analogRead (Read2);
rawADC3 = analogRead (Read2);
rawADC4 = analogRead (Read2);
rawADC5 = analogRead (Read2);
rawADC6 = analogRead (Read2);
rawADC7 = analogRead (Read2);
rawADC8 = analogRead (Read2);
rawADC9 = analogRead (Read2);
rawADC10 = analogRead (Read2);
rawADC11 = analogRead (Read2);
rawADC12 = analogRead (Read2);
rawADC13 = analogRead (Read2);
rawADC14 = analogRead (Read2);
rawADC15 = analogRead (Read2);
rawADC16 = analogRead (Read2);
rawADC17 = analogRead (Read2);
rawADC18 = analogRead (Read2);
rawADC19 = analogRead (Read2);
average = (rawADC0 + rawADC1 + rawADC2 + rawADC3 + rawADC4 + rawADC5 + rawADC6 + rawADC7 + rawADC8 + rawADC9 + rawADC10 + rawADC11 + rawADC12 + rawADC13 + rawADC14 + rawADC15 + rawADC16 + rawADC17 + rawADC18 + rawADC19) / 20;
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
average2 = 0;
count = 0;
if (rawADC0 <= average+percentADC && rawADC0 >= average-percentADC) {average2 = average2 + rawADC0; count++;}
if (rawADC1 <= average+percentADC && rawADC1 >= average-percentADC) {average2 = average2 + rawADC1; count++;}
if (rawADC2 <= average+percentADC && rawADC2 >= average-percentADC) {average2 = average2 + rawADC2; count++;}
if (rawADC3 <= average+percentADC && rawADC3 >= average-percentADC) {average2 = average2 + rawADC3; count++;}
if (rawADC4 <= average+percentADC && rawADC4 >= average-percentADC) {average2 = average2 + rawADC4; count++;}
if (rawADC5 <= average+percentADC && rawADC5 >= average-percentADC) {average2 = average2 + rawADC5; count++;}
if (rawADC6 <= average+percentADC && rawADC6 >= average-percentADC) {average2 = average2 + rawADC6; count++;}
if (rawADC7 <= average+percentADC && rawADC7 >= average-percentADC) {average2 = average2 + rawADC7; count++;}
if (rawADC8 <= average+percentADC && rawADC8 >= average-percentADC) {average2 = average2 + rawADC8; count++;}
if (rawADC9 <= average+percentADC && rawADC9 >= average-percentADC) {average2 = average2 + rawADC9; count++;}
if (rawADC10 <= average+percentADC && rawADC10 >= average-percentADC) {average2 = average2 + rawADC10; count++;}
if (rawADC11 <= average+percentADC && rawADC11 >= average-percentADC) {average2 = average2 + rawADC11; count++;}
if (rawADC12 <= average+percentADC && rawADC12 >= average-percentADC) {average2 = average2 + rawADC12; count++;}
if (rawADC13 <= average+percentADC && rawADC13 >= average-percentADC) {average2 = average2 + rawADC13; count++;}
if (rawADC14 <= average+percentADC && rawADC14 >= average-percentADC) {average2 = average2 + rawADC14; count++;}
if (rawADC15 <= average+percentADC && rawADC15 >= average-percentADC) {average2 = average2 + rawADC15; count++;}
if (rawADC16 <= average+percentADC && rawADC16 >= average-percentADC) {average2 = average2 + rawADC16; count++;}
if (rawADC17 <= average+percentADC && rawADC17 >= average-percentADC) {average2 = average2 + rawADC17; count++;}
if (rawADC18 <= average+percentADC && rawADC18 >= average-percentADC) {average2 = average2 + rawADC18; count++;}
if (rawADC19 <= average+percentADC && rawADC19 >= average-percentADC) {average2 = average2 + rawADC19; count++;}
average = average2 / count;
float voltage2 = ((float) average + CalibV ) / 1024.0 * VccReal;

lcd.setCursor(5, 1);
lcd.print(voltage2,3);lcd.print("V");

lcd.setCursor(12, 1);
lcd.print(" ");
lcd.setCursor(12, 1);
lcd.print(average);

// lcd.setCursor(17, 1);
// lcd.print(" ");
// lcd.setCursor(17, 1);
// lcd.print(count);


delay(200);

}

Το έχω, δύο μηνάκια δώσε μου ακόμα και θα αντικαταστήσω και το OCD κομμάτι με το σωστό που έγραψε ο Fire Doger :001_tt2:

selectronic
04-04-17, 11:58
Συνήλθε το Youtube, λινκ 1ου βίντεο (https://youtu.be/VwbOLS7kDYc) με τον κώδικα του manolena από ποστ #62 (ίδιος και στο #69), που δεν μετράει τάσεις για κάποιο αλλοπρόσαλλο λόγο.

2ο βίντεο (https://youtu.be/6imzle9ojvs) με τον "προσωρινό" κώδικα που έβαλα στο τέλος του #72.

Τέλος προς το παρών, ευχαριστώ για την βοήθεια παιδιά!

Fire Doger
04-04-17, 12:26
Έχεις 2 κατηγορίες μεταβλητών, τις global και τις local.
Αν μια μεταβλητή την ορίσεις μέσα σε μια συνάρτηση τότε υπάρχει μόνο μέσα σε αυτήν την συνάρτηση.
Μόλις έρθει το } σταματάει να υπάρχει. Αν δηλαδή έχεις 2 μεταβλητές "readVcc" σε διαφορετικές συναρτήσεις δεν έχουν καμία σχέση μεταξύ τους.

Για να μεταφέρεις μια τιμή σε άλλη συνάρτηση πρέπει να την πασάρεις και να την υποδεχτεί η συνάρτηση.
Πχ το print("123") πασάρει το "123".
και η void print(string xxx){...} υποδέχεται ενα string και το αποθηκεύει με το όνομα xxx. Επίσης για να σου επιστρέψει κατι μια συνάρτηση ακολουθεί διαδικασία με παρόμοια σκεπτικό. (Αποστολή-υποδοχή)
Οπότε αν ορίσεις την readVcc στο setup στο loop δεν υπάρχει.

Οι global ορίζονται έξω από συνάρτηση, χύμα τελείως και υπάρχουν παντού για πάντα! Το κακό είναι πως αν τα έχεις όλα global μπορεί να γεμίσει η ram κάποια στιγμή, ενώ με τις local όταν κλείνει η συνάντηση πάνε κουβά οσα δεν χρειάζεσαι και καθαρίζει η Ram.

selectronic
05-04-17, 06:47
Έχεις 2 κατηγορίες μεταβλητών, τις global και τις local.
Αν μια μεταβλητή την ορίσεις μέσα σε μια συνάρτηση τότε υπάρχει μόνο μέσα σε αυτήν την συνάρτηση.
Μόλις έρθει το } σταματάει να υπάρχει. Αν δηλαδή έχεις 2 μεταβλητές "readVcc" σε διαφορετικές συναρτήσεις δεν έχουν καμία σχέση μεταξύ τους.

Για να μεταφέρεις μια τιμή σε άλλη συνάρτηση πρέπει να την πασάρεις και να την υποδεχτεί η συνάρτηση.
Πχ το print("123") πασάρει το "123".
και η void print(string xxx){...} υποδέχεται ενα string και το αποθηκεύει με το όνομα xxx. Επίσης για να σου επιστρέψει κατι μια συνάρτηση ακολουθεί διαδικασία με παρόμοια σκεπτικό. (Αποστολή-υποδοχή)
Οπότε αν ορίσεις την readVcc στο setup στο loop δεν υπάρχει.

Οι global ορίζονται έξω από συνάρτηση, χύμα τελείως και υπάρχουν παντού για πάντα! Το κακό είναι πως αν τα έχεις όλα global μπορεί να γεμίσει η ram κάποια στιγμή, ενώ με τις local όταν κλείνει η συνάντηση πάνε κουβά οσα δεν χρειάζεσαι και καθαρίζει η Ram.

Αυτά παθαίνεις αν δεν έχεις πρώτα μάθει την γλώσσα αλλά ξεκινάς να κόβεις-ράβεις κομμάτια κώδικα που βρήκες...
Έκανα λίγο διάβασμα, όπως:
https://www.arduino.cc/en/Reference/Scope
https://www.arduino.cc/en/tutorial/variables
(https://www.arduino.cc/en/tutorial/variables)https://www.arduino.cc/en/Reference/Loop (τελείως κενό)
και το πιο χρήσιμο ήταν εδώ (https://en.wikipedia.org/wiki/Global_variable#C_and_C.2B.2B) που περιγράφει το πως μπορείς να κάνεις αυτό που θέλω, αλλά δεν μπορώ να καταλάβω τι νόημα έχουν οι μεταβλητές "overShared" και "overSharedToo" που δηλώνει στην αρχή και μετά δεν χρησιμοποιεί πουθενά (???), αλλά δεν κατάφερα να το προσαρμόσω στον κώδικά μου...
Σε άλλα forum που κοίταξα, όλοι λένε το ίδιο: "δεν είναι καλό να είναι global οι μεταβλητές όπως σε άλλες γλώσσες, κάνει κακό γιατί Χ Ψ Ω! Πρέπει να είναι περιορισμένες για τους Υ Ζ Φ λόγους"...
Δεν βρήκα όμως (γιατί σίγουρα κάπου υπάρχει) λύση που να δουλεύει για εμένα.
Εγώ θα έχω κατά την ροή του προγράμματος μία μεταβλητή που θα πρέπει να αλλάζει τιμές (πχ readVcc) και άλλη μία που θα αλλάξει τιμής σε συνάρτηση με την μέτρηση της Χ τιμής (πχ analogRead(A0)) αλλά και σε συνάρτηση με την εκάστοτε τιμή της πρώτης "μεταβλητής".
Δεν μπορώ να κάνω την πρώτη "σταθερή" (static int xxxxxxxx) και να την δηλώσω πριν το setup, γιατί πρέπει να αλλάζει τιμές...
Και αν το κομμάτι που μετράει την πρώτη μεταβλητή είναι ένα function (measureVcc) και το κομμάτι που μετράει την δεύτερη είναι σε άλλο function (measureAnalogA0), τότε πρέπει να υπάρχει επικοινωνία μεταξύ των δύο, πρέπει το measureVcc να αποθηκεύει το αποτέλεσμά του κάπου που να μπορεί να το διαβάσει το measureAnalogA0.

Πως γίνεται αυτό?

Εγώ από το παρακάτω που δουλεύει,


#include <LiquidCrystal.h>


//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
//================================================== =================
void setup()
{
lcd.begin(16, 2);//
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);


long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV
float VccReal = (float) readVcc / 1000;


lcd.setCursor(0, 1);
lcd.print(VccReal,2);

float voltage = analogRead (A0) / 1024.0;
lcd.setCursor(7, 0);
lcd.print(voltage,3);lcd.print("V");

float adjustedVoltage = (analogRead (A0) / 1024.0) * VccReal;
lcd.setCursor(7, 1);
lcd.print(adjustedVoltage,3);lcd.print("V");

delay(200);

}

Προσπάθησα μεταξύ άλλων που δεν έκαναν καν compile, το παρακάτω που θα έπρεπε να δουλεύει, αλλά δεν... Κάνει compile μεν αλλά την adjustedVoltage την γράφει "0.000V" στην οθόνη...

#include <LiquidCrystal.h>


//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
volatile float VccReal;
//================================================== =================
void setup()
{
lcd.begin(16, 2);//
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);

measureVcc();
measureAnalogA0();

delay(200);
}

void measureVcc()
{
long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV
float VccReal = (float) readVcc / 1000;

lcd.setCursor(0, 1);
lcd.print(VccReal,2);

}

void measureAnalogA0()
{
float voltage = analogRead (A0) / 1024.0;
lcd.setCursor(7, 0);
lcd.print(voltage,3);lcd.print("V");

float adjustedVoltage = (analogRead (A0) / 1024.0) * VccReal;
lcd.setCursor(7, 1);
lcd.print(adjustedVoltage,3);lcd.print("V");

}

EDIT:

Το βρήκα! Είχα κάνει το λάθος και είχα αφήσει άλλο ένα "float" στο function 'measureVcc' οπότε στην ουσία έφτιαχνε μία νέα και fuction-only (σωστά?) VccReal αντί να αλλάζει την ήδη υπάρχουσα που δηλώνω με volatile στην αρχή του κώδικα. Έσβησα απλώς αυτό το "float" και δουλεύει!


#include <LiquidCrystal.h>


//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7);
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
volatile float VccReal;
//================================================== =================
void setup()
{
lcd.begin(16, 2);//
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);

measureVcc();
measureAnalogA0();

delay(200);
}

void measureVcc()
{
long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV
VccReal = (float) readVcc / 1000; // <--------------------------------------------εδώ ήταν το εξτρά "float" στη αρχή που χάλαγε τον κώδικα

lcd.setCursor(0, 1);
lcd.print(VccReal,2);

}

void measureAnalogA0()
{
float voltage = analogRead (A0) / 1024.0;
lcd.setCursor(7, 0);
lcd.print(voltage,3);lcd.print("V");

float adjustedVoltage = (analogRead (A0) / 1024.0) * VccReal;
lcd.setCursor(7, 1);
lcd.print(adjustedVoltage,3);lcd.print("V");

}

Το να μετράω την Vcc θα το χρησιμοποιώ τώρα στις δοκιμές γιατί θα υπολογίζω με βάσει την Vcc (και όχι την 1,1Vref) την τάση στις αναλογικές εισόδους, και η Vcc αλλάζει από ~4.6V όταν είναι ο Arduino στο USB, σε ~5.0V όταν του δίνω 12V στο πιν "Vin".
Και στο τέλος μάλλον θα το αφήσω γιατί κακό δεν κάνει και παρόλο που με τον εσωτερικό 10bit ADC κτλ δεν θα υπάρχει μεγάλη διαφορά αν αλλάξει η Vcc (λόγο αύξησης θερμοκρασίας κτλ) κατά πχ 10mV, σαν τρόπος μέτρησης είναι καλύτερο από το απλώς να έχω συνδέσει την Vcc σε μία Αναλογική Είσοδο και να την μετράω έτσι, αφού η Atmel λέει ότι η 1.1Vtref είναι "πολύ" σταθερή, σωστά?

selectronic
05-04-17, 08:00
Ο "πλήρες" κώδικας, με τις 20 μετρήσεις AnalogRead κτλ:

Έβαλα το κομμάτι με τα κενά πιο κάτω, ώστε όταν η τιμή 0-1023 του ADC ("average") είναι μόνο 3 ψηφία να γράφει ένα κενό, αν είναι κάτω από 2 ψηφία να γράφει άλλο ένα (+1 αφού είναι πάλι <999 = 2 κενά) και αν είναι μονοψήφιος να γράφει ένα ακόμα.

lcd.print(average); // είναι ακαριαίος με τιμές 0 - 1023
if(average < 999) {lcd.print(" ");}
if(average < 99) {lcd.print(" ");}
if(average < 9) {lcd.print(" ");}


Το κομμάτι που δηλώνω "long readVcc;" το έβαλα στο function του measureVcc...


Ο κώδικας μέχρι στιγμής που πρώτα μετράει την Vcc και μετρά μετράει τις A0 και A1 σε σχέση με την Vcc (0-5V στα Α0 και Α1 = 0-1023 ADC):
EDIT - Άλλαξα το κομμάτι με τις 20 μετρήσεις στο πιο σωστό που υπέδειξε ο Fire Doger, παίζει τέλεια thanks!

#include <LiquidCrystal.h>

//================================================== =================
LiquidCrystal lcd(2, 4, 6, 7, 8, 9); // Green 20x2 LCD
// LiquidCrystal lcd(2, 8, 4, 5, 6, 7); // Blue 16x2 LCD
//================================================== =================
long Vref11 = 1122000L; // Boards Internal 1.1Vref
float CalibV = 2.0; // 'Calibrate' value
int Read1 = A0;
int Read2 = A2;
float OnePercentADC, percentADC;
int average;
float average2 = 0;
int count = 0;
volatile float VccReal;
//================================================== =================
void setup()
{
lcd.begin(16, 2); // Green 10x2 LCD
// lcd.begin(16, 2); // Blue 16x2 LCD
}
//================================================== =================
void loop()
{
lcd.setCursor(0, 0);
lcd.print(millis() / 1000);

measureVcc();
ReadAndPrintA0();
ReadAndPrintA1();

delay(200);
}

void measureVcc()
{
long readVcc;
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
readVcc = ADCL;
readVcc |= ADCH<<8;
readVcc = Vref11 / readVcc; // Back-calculate AVcc in mV
VccReal = (float) readVcc / 1000;

lcd.setCursor(0, 1);
lcd.print(VccReal,2);

}
//================================================== =================
void ReadAndPrintA0()
{
//take 20 measurements, NEW and improved method
int rawADC[20];
for(byte i =0; i<20; i ++)
rawADC[i] = analogRead (Read1);

// Make first average of those values
int average =0;
for(byte i=0; i<20; i++){average+=rawADC[i];}
average = average/20;

// Make the 'int' average value into a 'float', calc 1/1000 of that average value and select percent under/over to be "discarded"
OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
// From the previous values, exclude those that are 10% more/less than made 'average' value, and re-calculate a new average
average2 = 0;
count = 0;

for(byte i=0; i<20; i++)
if (rawADC[i] <= average+percentADC && rawADC[i] >= average-percentADC) {average2 = average2 + rawADC[i]; count++;}

average = average2 / count;
float voltage = ((float) average + CalibV ) / 1024.0 * VccReal;


lcd.setCursor(5, 0);
lcd.print(voltage,3);
lcd.print("V");


lcd.setCursor(12, 0);
lcd.print(average);
if(average < 999) {lcd.print(" ");}
if(average < 99) {lcd.print(" ");}
if(average < 9) {lcd.print(" ");}

lcd.setCursor(17, 0);
lcd.print(count);
if(count < 999) {lcd.print(" ");}
if(count < 99) {lcd.print(" ");}
if(count < 9) {lcd.print(" ");}
}
//================================================== =================
void ReadAndPrintA1()
{
int rawADC[20];
for(byte i =0; i<20; i ++)
rawADC[i] = analogRead (Read2);

int average =0;
for(byte i=0; i<20; i++){average+=rawADC[i];}
average = average/20;

OnePercentADC = (float) average / 1000;
percentADC = OnePercentADC * 6; // Percent of "tolerance" before a value is discarted, in -Thousands- of the average value
average2 = 0;
count = 0;

for(byte i=0; i<20; i++)
if (rawADC[i] <= average+percentADC && rawADC[i] >= average-percentADC) {average2 = average2 + rawADC[i]; count++;}

average = average2 / count;
float voltage2 = ((float) average + CalibV ) / 1024.0 * VccReal;


lcd.setCursor(5, 1);
lcd.print(voltage2,3);
lcd.print("V");


lcd.setCursor(12, 1);
lcd.print(average);
if(average < 999) {lcd.print(" ");}
if(average < 99) {lcd.print(" ");}
if(average < 9) {lcd.print(" ");}


lcd.setCursor(17, 1);
lcd.print(count);
if(count < 999) {lcd.print(" ");}
if(count < 99) {lcd.print(" ");}
if(count < 9) {lcd.print(" ");}
}
//================================================== =================
//================================================== =================
//================================================== =================
//================================================== =================

Και "ο πράσινος" ζει !!!

http://i.imgur.com/beI0wIq.jpg

picdev
05-04-17, 09:58
για καλύτερη ακρίβεια μπορείς να βάλεις ενα IC με Vref , που δεν θα αλλάζει ανάλογα με τη θερμοκρασία πχ

selectronic
05-04-17, 11:21
για καλύτερη ακρίβεια μπορείς να βάλεις ενα IC με Vref , που δεν θα αλλάζει ανάλογα με τη θερμοκρασία πχ

Το έχω υπόψιν μου, ευχαριστώ.

Προς το παρών έκανα δοκιμή με τα 0-45V μέσω διαιρέτη (~0-4V) και από ότι βλέπω μάλλον θα πρέπει να αρχίσω το διάβασμα σχετικά με τους "πίνακες" που ανέφερε ο pstratos, δηλαδή να υπάρχει μία διαφορετική 'CalibV' για κάθε μία από τις 1024 τιμές του ADC... Το απλό 'CalibV = 2.0' που είναι "ΟΚ για εμένα" στα 0-1V ή 0-5V μέτρησης πέφτει πολύ έξω όταν πολλαπλασιάζω 11.25 φορές την τάση για να υπολογίσω τα πχ 40V.

Και γίνεται και ο κακός χαμός με θόρυβο (θέλω να πιστεύω ότι αυτό είναι), από εκεί που είχα συνήθως σταθερά 19-20 τιμές 'count', τώρα πέφτει τόσο χαμηλά που αλλάζει τιμή στην οθόνη για πλάκα, ιδίως στις πιο χαμηλές τάσεις...
Θα δοκιμάσω να αυξήσω και το ποσοστό διαφοράς πάνω από το οποίο κόβει τιμές, τώρα είναι αρκετά συντηρητικό στο 0.6% νομίζω.
Το πρώτο τεστ στα 40V είναι, θα καλυτερέψει μέρα με την μέρα :wiink:


https://youtu.be/RcUIqVXuDGk

selectronic
06-04-17, 16:49
Δυστυχώς κόλλησα ξανά...

Διάβασα για το πως να φτιάξω array με τιμές, αλλά στην πορεία κόλλησα σε κάτι πιο απλό: δεν μπορώ να φτιάξω μία "if" ρουτίνα που να λειτουργεί! (με η χωρίς "else") :cursing:

Φτιάχνω μία μεταβλητή "Switch" που παίρνει τιμές "0" ή "1" ανάλογα με το αν έχω ένα διακοπτάκι on/off και προσπαθώ να αλλάζω κάτι στον κώδικα ανάλογα με την τιμή που έχει κάθε φορά η "Switch".
Το παρακάτω δουλεύει και τυπώνει την "Adjusted" σταθερά στα "0.010" και την "Switch" που αλλάξει μεταξύ "0" και "1" ανάλογα με τον πραγματικό διακόπτη.


#include <LiquidCrystal.h>

//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7); // Blue 16x2 LCD
//================================================== =================
int Read0 = A0;
float Adjusted = 0.01;
int Switch;
//================================================== =================
void setup()
{
lcd.begin(16, 2); // Blue 16x2 LCD
}
//================================================== =================
void loop()
{
int readSwitch = analogRead (Read0);
if (readSwitch < 2) {Switch = 0;} else {Switch = 1;}

lcd.setCursor(5, 0);
lcd.print(Adjusted,3);

lcd.setCursor(14, 0);
lcd.print(Switch);

delay(200);
}
//================================================== =================
//================================================== =================
//================================================== =================

Όταν βάζω την γραμμή με την εντολή "if (Switch = 1) {Adjusted = Adjusted - 0.001;}" πριν την γραμμή που τυπώνει την "Switch" στην οθόνη, το αποτέλεσμα είναι σαν να έχει κολλήσει ο διακόπτης στο "1": έχω στην LCD την "Adjusted" να ξεκινάει από 0.01 και να ανεβαίνει συνέχεια και την "Switch" να είναι πάντα "1", παρόλο που ανοιγοκλείνω τον διακόπτη...


#include <LiquidCrystal.h>

//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7); // Blue 16x2 LCD
//================================================== =================
int Read0 = A0;
float Adjusted = 0.01;
int Switch;
//================================================== =================
void setup()
{
lcd.begin(16, 2); // Blue 16x2 LCD
}
//================================================== =================
void loop()
{
int readSwitch = analogRead (Read0);
if (readSwitch < 2) {Switch = 0;} else {Switch = 1;}

lcd.setCursor(5, 0);
lcd.print(Adjusted,3);

if (Switch = 1) {Adjusted = Adjusted + 0.001;}
lcd.setCursor(14, 0);
lcd.print(Switch);

delay(200);
}
//================================================== =================
//================================================== =================
//================================================== =================

Αν βάλω την if γραμμή μετά την "lcd.print(Switch);", στην LCD πάλι η "Adjusted" ανεβαίνει συνεχώς, αλλά τώρα αλλάζει η "Switch" από "0" σε "1"


#include <LiquidCrystal.h>

//================================================== =================
LiquidCrystal lcd(2, 8, 4, 5, 6, 7); // Blue 16x2 LCD
//================================================== =================
int Read0 = A0;
float Adjusted = 0.01;
int Switch;
//================================================== =================
void setup()
{
lcd.begin(16, 2); // Blue 16x2 LCD
}
//================================================== =================
void loop()
{
int readSwitch = analogRead (Read0);
if (readSwitch < 2) {Switch = 0;} else {Switch = 1;}

lcd.setCursor(5, 0);
lcd.print(Adjusted,3);

lcd.setCursor(14, 0);
lcd.print(Switch);
if (Switch = 1) {Adjusted = Adjusted + 0.001;}

delay(200);
}
//================================================== =================
//================================================== =================
//================================================== =================


Προφανώς κάτω κάτι λάθος στην σύνταξη της "if", αλλά που ??? Κοίταξα την σελίδα του Arduino για την εντολή (https://www.arduino.cc/en/Reference/If) και δεν βλέπω τι κάνω λάθος...

Fire Doger
06-04-17, 17:12
if (Switch = 1)
Σημαίνει, κάνε το Switch 1, για το τι ελέγχει δεν είμαι σίγουρος, ή την επιτυχία του να το κάνεις 1 ή την Switch σαν να ήταν true/false. Όπως και να έχει δεν είναι αυτό που θες.

Αυτό που θέλεις είναι
if (Switch == 1)
Τα ίσον ίσον είναι η σύγκριση.

=============

switch (Switch){
case 0:
.
.
.
break;

case 1:
.
.
.
break;

default: //αν δεν είναι κάτι απ' τα παραπάνω
break;
}

Επίσης δεν βάζεις ποτέ κάτι μέσα στο Switch, ίσως σου έβγαζε error σαν unassigned ή κάτι τέτοιο. Μπορείς όταν την ορίζεις να βάλεις και μια τιμή. πχ int Switch=0;
Και στην C κάποια ονόματα είναι δεσμευμένα όπως το switch, θα την άλλαζα σε κάτι που να μην μοιάζει τόσο πολύ.

selectronic
06-04-17, 17:31
Να 'σαι καλά, τόσο απλό!