Buona sera a tutti (scusate ma sono autodidatta in tutto ciò che riguarda i computer ) sono ormai parecchi mesi che cerco di studiare per imparare ad usare Arduino (magari lo avessi avuto trent'anni fa!!!!!!) , su Arduino Hub ho trovato uno scketch che calza a pennello per un tornio auto costruito, ora dopo parecchi problemi sono riuscito a farlo funzionare con un Arduino Nano (non originale) , colto da prematuro entusiasmo ho comprato un "Every" originale e qui iniziano i problemi, non mi accetta il programma ( ho provato numerosi scketch semplici presi dal menù "esempi" e funzionano tutti, non so più cosa provare, ora , non essendo sicuro di scrivere nel modo e nel posto giusto nel forum qualcuno potrebbe chiarirmi le idee a proposito ? posso eventualmente allegare lo scketch di github. in che modo non vorrei mancare di rispetto a nessuno! grazie in anticipo.
Buongiorno e benvenuto nella sezione Italiana del forum,
cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento, fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.
Grazie,
Guglielmo
P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte verrebbero temporaneamente nascoste), quindi ti consiglio di farla al più presto. ![]()
Il problema è che, a dispetto del nome, Arduino Nano ed Arduino Nano Every sono due cose totalmente diverse, la prima monta una MCU della vecchia serie AVR (ATmega328P), la seconda una MCU di nuova generazione (ATmega4809) e ... se chi scrive le librerie, non le aggiorna per supportare entrambe le MCU, ovviamnete NON va nulla (specie se sono librerie che lavorano a basso livello, sulle porte, sui timers e sui registri).
Quindi, non mi sorprende affatto che codice per Arduino Nano non funzioni su Arduino Nano Every ... bisogna vedere cosa usa e la compatibilità che è data ... ![]()
Guglielmo
Grazie per la solerte risposta, piacere di sentirla, purtroppo conferma i miei timori, comprerò un altro Arduino ,questa volta Nano sicuramente " original " , credo sicuramente più affidabile dei
cloni !. Un ultima domanda, secondo voi per quanto saranno ancora disponibili le " vecchie " schede
basate sul 328?
Il ATmega328P è tra i prodotti che ancora sono in produzione, anche se, come per quasi tutti i chip, attualmente con tempi di consegna ... da piangere ![]()
"Arduino Nano Every" è un Arduino originale ...
... solo che usa i nuovi chip (ATmega4809), più potenti e performanti ![]()
Guglielmo
Metti pure il link allo sketch, magari la modifica per riuscire a compilare con il "nano every" è più semplice di quello che può sembrare.
Provo a "linkare"il codice e l'autore , grazie per il tempo dedicatomi,
--- ho eliminato io il link al progetto in cui si parla di tensioni oltre le bassissima tensione. gpb01 ---
// Universal_AC_motor_PID_control_pulley_ratio.ino
#include <avr/io.h>
#include <avr/interrupt.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Rotary.h>
#include <PID_v1.h>
#define TACHO 3 // tacho signals input pin
#define DETECT 2 // zero cross detect pin
#define GATE 17 // TRIAC gate pin
#define RANGE1 9 // range one switch pin
#define RANGE2 10 // range two switch pin
#define BUTTON 4 // rottary encoder button pin
#define RELAY 5 // relay pin
#define PULSE 2 // number of triac trigger pulse width counts. One count is 16 microseconds
#define TACHOPULSES 8 // number of pulses per revolution
unsigned int RPM; // real rpm variable
unsigned int count; // tacho pulses count variable
unsigned int lastcount = 0; // additional tacho pulses count variable
unsigned long lastcounttime = 0;
unsigned long lastflash;
unsigned long lastpiddelay = 0;
unsigned long previousMillis = 0;
unsigned long lastDebounceTime = 0;
const int sampleRate = 1; // Variable that determines how fast our PID loop
const int rpmcorrection = 86; // had to add this parameter to have real RPM equal to desired RPM
const int lcdinterval = 2000; // lcd refresh interval in milliseconds
const int protection = 2000; // protection will switch on when real rpm exceeds desired by value
const int debounceDelay = 50; // the debounce time; increase if the output flickers
const int minoutputlimit = 80; // limit of PID output
const int maxoutputlimit = 540; // limit of PID output
const int mindimminglimit = 80; // the shortest delay before triac fires
const int maxdimminglimit = 625; // for 60Hz will be 520
const int minrpmR1 = 300; // min RPM of the range 1
const int maxrpmR1 = 1500; // max RPM of the range 1
const int minrpmR2 = 1500; // min RPM of the range 2
const int maxrpmR2 = 3500; // max RPM of the range 2
const int risetime = 100; // RPM rise time delay in microseconds (risetime x RPM)
int dimming = 540; // this should be the same as maxoutputlimit
int counterR1; // desired RPM counter for range 1
int counterR2; // desired RPM counter for range 2
int desiredRPM;
int tempcounter = 100;
byte range;
byte lastRangeState = 0;
byte relayState = LOW; // the current state of the relay pin
byte buttonState; // the current reading from the input pin
byte lastButtonState = HIGH; // the previous reading from the input pin
bool loopflag = false; // flag for soft start
bool startflag = false; // flag for motor start delay
bool runflag = false; // flag for motor running state
double ratio = 2.96; // pulley ratio. Set to 1 if no pulley
// ratio needed (must be higher than 0!)
double Setpoint, Input, Output; // define PID variables
double sKp = 0.1, sKi = 0.2, sKd = 0; // PID tuning parameters for starting motor
double rKp = 0.25, rKi = 1, rKd = 0; // PID tuning parameters for runnig motor
LiquidCrystal_I2C lcd(0x26, 16, 2); // set the LCD address to 0x26 for a 16 chars and 2 line display
Rotary r = Rotary(12, 11); // define rottary encoder and pins
PID myPID(&Input, &Output, &Setpoint, sKp, sKi, sKd, DIRECT); // define PID variables and parameters
void setup() {
Serial.begin(115200);
// set up pins
pinMode(BUTTON, INPUT); // set the button pin
pinMode(RELAY, OUTPUT); // set the relay pin
pinMode(DETECT, INPUT); // set the zero cross detect pin
pinMode(GATE, OUTPUT); // set the TRIAC gate control pin
pinMode(TACHO, INPUT); // set the tacho pulses detect pin
pinMode(RANGE1, INPUT); // set the range 1 switch pin
pinMode(RANGE2, INPUT); // set the range 1 switch pin
digitalWrite(BUTTON, HIGH); // turn on pullup resistors
digitalWrite(RANGE1, HIGH); // turn on pullup resistors
digitalWrite(RANGE2, HIGH); // turn on pullup resistors
digitalWrite(RELAY, relayState); // initialize relay output
counterR1 = minrpmR1; // assign start value for range 1
counterR2 = minrpmR2; // assign start value for range 2
Input = 200; // asiign initial value for PID
Setpoint = 200; // asiign initial value for PID
//turn the PID on
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(minoutputlimit, maxoutputlimit);
myPID.SetSampleTime(sampleRate); // Sets the sample rate
// set up Timer1
OCR1A = 100; // initialize the comparator
TIMSK1 = 0x03; // enable comparator A and overflow interrupts
TCCR1A = 0x00; // timer control registers set for
TCCR1B = 0x00; // normal operation, timer disabled
// set up zero crossing interrupt IRQ0 on pin 2.
// set up tacho sensor interrupt IRQ1 on pin3
attachInterrupt(0, zeroCrossingInterrupt, RISING);
attachInterrupt(1, tacho, FALLING);
lcd.init(); // initialize the lcd
lcd.backlight(); // turn on the backlight
// check the RPM range state at startup and display it
int rangeOne = digitalRead(RANGE1);
int rangeTwo = digitalRead(RANGE2);
if (rangeOne == 1 && rangeTwo == 1) {
range = 0;
range0();
}
if (rangeOne == 0 && rangeTwo == 1) {
range = 1;
RPMrange1();
}
if (rangeOne == 1 && rangeTwo == 0) {
range = 2;
RPMrange2();
}
}
// Interrupt Service Routines
void zeroCrossingInterrupt() { // zero cross detect
TCCR1B = 0x04; // start timer with divide by 256 input
TCNT1 = 0; // reset timer - count from zero
OCR1A = dimming; // set the compare register brightness desired.
}
ISR(TIMER1_COMPA_vect) { // comparator match
if (startflag == true) { // flag for start up delay
digitalWrite(GATE, HIGH); // set TRIAC gate to high
TCNT1 = 65536 - PULSE; // trigger pulse width
}
}
ISR(TIMER1_OVF_vect) { // timer1 overflow
digitalWrite(GATE, LOW); // turn off TRIAC gate
TCCR1B = 0x00; // disable timer stops unintended triggers
}
// RPM counting routine
void tacho() {
count++;
unsigned long time = micros() - lastflash;
float time_in_sec = ((float)time + rpmcorrection) / 1000000;
float prerpm = 60 / time_in_sec;
RPM = prerpm / TACHOPULSES;
lastflash = micros();
}
void loop() {
// check the RPM range switch state
int rangeOne = digitalRead(RANGE1);
int rangeTwo = digitalRead(RANGE2);
if (rangeOne == 1 && rangeTwo == 1) {
range = 0;
}
if (rangeOne == 0 && rangeTwo == 1) {
range = 1;
desiredRPM = counterR1 * ratio;
}
if (rangeOne == 1 && rangeTwo == 0) {
range = 2;
desiredRPM = counterR2 * ratio;
}
// check the RPM range switch state changes
if (range != lastRangeState) {
if (range == 0) {
range0();
runflag = false;
startflag = false; // flag to turn off triac before relay turns off
delay (300); // delay to prevent sparks on relay contacts
digitalWrite(RELAY, LOW);
relayState = LOW;
}
if (range == 1) {
RPMrange1();
}
if (range == 2) {
RPMrange2();
}
if (relayState == LOW && range != 0) {
motorStateStop();
}
}
lastRangeState = range;
// check the start / stop button state
if (range != 0) {
int reading = digitalRead(BUTTON); // read the state of the switch into a local variable:
if (reading != lastButtonState) { // If the switch changed, due to noise or pressing
lastDebounceTime = millis(); // reset the debouncing timer
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) { // if the button state has changed:
buttonState = reading;
if (buttonState == LOW) { // only toggle the relay if the new button state is LOW
relayState = !relayState;
if (relayState == HIGH) {
loopflag = true;
digitalWrite(RELAY, relayState); // set the Relay:
delay (300); // delay to prevent sparks on relay contacts
startflag = true; // flag to start motor
}
if (relayState == LOW) {
Setpoint = 200;
Input = 200;
runflag = false;
startflag = false;
delay (300); // delay to prevent sparks on relay contacts
digitalWrite(RELAY, relayState); // set the Relay:
motorStateStop();
}
}
}
}
lastButtonState = reading; // save the reading. Next time through the loop, it'll be the lastButtonState:
}
//rotarry encoder process
unsigned char result = r.process();
if (range == 1 && result == DIR_CW) {
if (counterR1 >= 500)
{
counterR1 += 50;
}
else counterR1 += 20;
if (counterR1 >= maxrpmR1) {
counterR1 = maxrpmR1;
}
RPMrange1();
}
else if (range == 1 && result == DIR_CCW) {
if (counterR1 <= 500)
{
counterR1 -= 20;
}
else counterR1 -= 50;
if (counterR1 <= minrpmR1) {
counterR1 = minrpmR1;
}
RPMrange1();
}
if (range == 2 && result == DIR_CW) {
counterR2 += 100;
if (counterR2 >= maxrpmR2) {
counterR2 = maxrpmR2;
}
RPMrange2();
}
else if (range == 2 && result == DIR_CCW) {
counterR2 -= 100;
if (counterR2 <= minrpmR2) {
counterR2 = minrpmR2;
}
RPMrange2();
}
//soft start
if (loopflag == true) {
myPID.SetTunings(sKp, sKi, sKd); // Set the PID gain constants and start
int i = (desiredRPM - tempcounter);
for (int j = 1; j <= i; j++) {
Input = RPM;
Setpoint = tempcounter;
myPID.Compute();
dimming = map(Output, minoutputlimit, maxoutputlimit, maxoutputlimit, minoutputlimit); // inverse the output
dimming = constrain(dimming, mindimminglimit, maxdimminglimit); // check that dimming is in 20-625 range
tempcounter++;
delayMicroseconds (risetime);
}
if (tempcounter >= desiredRPM) {
lastcounttime = millis();
lastpiddelay = millis();
loopflag = false;
runflag = true;
tempcounter = 100;
}
}
// normal motor running state
if (relayState == HIGH && loopflag == false) {
unsigned long piddelay = millis();
if ((piddelay - lastpiddelay) > 1000) { // delay to switch PID values. Prevents hard start
myPID.SetTunings(rKp, rKi, rKd); // Set the PID gain constants and start
lastpiddelay = millis();
}
Input = RPM;
Setpoint = desiredRPM;
myPID.Compute();
dimming = map(Output, minoutputlimit, maxoutputlimit, maxoutputlimit, minoutputlimit); // reverse the output
dimming = constrain(dimming, mindimminglimit, maxdimminglimit); // check that dimming is in 20-625 range
}
// diagnose a fault and turn on protection
unsigned long counttime = millis();
if (counttime - lastcounttime >= 1000) {
if (count == 0 && relayState == HIGH && runflag == true) {
startflag = false; // flag to turn off triac before relay turns off
delay (300); // delay to prevent sparks on relay contacts
digitalWrite(RELAY, LOW);
relayState = LOW;
stuckerror();
}
lastcount = count;
count = 0;
lastcounttime = millis();
}
//reset rpm after motor stops
if (count == 0 && relayState == LOW) {
RPM = 0;
}
// protection against high rpm. i e triac damage
if (relayState == HIGH && RPM > desiredRPM + protection) {
startflag = false; // flag to turn off triac before relay turns off
delay (300); // delay to prevent sparks on relay contacts
digitalWrite(RELAY, LOW);
relayState = LOW;
exceederror();
}
// real RPM display
if (relayState == HIGH && range != 0) {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= lcdinterval) {
previousMillis = currentMillis;
int rpmdisplay = RPM / ratio;
lcd.setCursor(0, 1);
lcd.print("Real RPM: ");
if (rpmdisplay >= 1000) {
lcd.setCursor(12, 1);
lcd.print(rpmdisplay);
}
else if (rpmdisplay < 1000) {
lcd.setCursor(12, 1);
lcd.print(" ");
lcd.setCursor(13, 1);
lcd.print(rpmdisplay);
}
}
}
}
void range0() {
lcd.setCursor(0, 0);
lcd.print(" Please select ");
lcd.setCursor(0, 1);
lcd.print(" the RPM range! ");
}
void motorStateStop() {
lcd.setCursor(0, 1);
lcd.print (" Press START ");
}
void RPMrange1() {
lcd.setCursor(0, 0);
lcd.print("R1 RPM set: ");
if (counterR1 >= 1000) {
lcd.setCursor(12, 0);
lcd.print(counterR1);
}
else {
lcd.setCursor(12, 0);
lcd.print(" ");
lcd.setCursor(13, 0);
lcd.print(counterR1);
}
}
void RPMrange2() {
lcd.setCursor(0, 0);
lcd.print("R2 RPM set: ");
lcd.setCursor(12, 0);
lcd.print(counterR2);
}
void exceederror() {
lcd.clear();
while (1) {
lcd.setCursor(5, 0);
lcd.print("ERROR!");
lcd.setCursor(2, 1);
lcd.print("TRIAC DAMAGE");
}
}
void stuckerror() {
lcd.clear();
while (1) {
lcd.setCursor(5, 0);
lcd.print("ERROR!");
lcd.setCursor(2, 1);
lcd.print("MOTOR STUCK!");
}
}
Quel programma fa uso di moduli che sono nella AVR libc:
#include <avr/io.h>
#include <avr/interrupt.h>
... il ATmega4809 NON è tra le MCU suportare dalla AVR libc (come ben visibile QUI e come riporto di seguito) e quindi, ovviamente, va in errore.
Le MCU supportate dall'attuale versione della libreria sono:
megaAVR Devices:
atmega103
atmega128
atmega128a
atmega1280
atmega1281
atmega1284
atmega1284p
atmega16
atmega161
atmega162
atmega163
atmega164a
atmega164p
atmega164pa
atmega165
atmega165a
atmega165p
atmega165pa
atmega168
atmega168a
atmega168p
atmega168pa
atmega16a
atmega2560
atmega2561
atmega32
atmega32a
atmega323
atmega324a
atmega324p
atmega324pa
atmega325
atmega325a
atmega325p
atmega325pa
atmega3250
atmega3250a
atmega3250p
atmega3250pa
atmega328
atmega328p
atmega48
atmega48a
atmega48pa
atmega48pb
atmega48p
atmega64
atmega64a
atmega640
atmega644
atmega644a
atmega644p
atmega644pa
atmega645
atmega645a
atmega645p
atmega6450
atmega6450a
atmega6450p
atmega8
atmega8a
atmega88
atmega88a
atmega88p
atmega88pa
atmega88pb
atmega8515
atmega8535
tinyAVR Devices:
attiny4
attiny5
attiny10
attiny11 [1]
attiny12 [1]
attiny13
attiny13a
attiny15 [1]
attiny20
attiny22
attiny24
attiny24a
attiny25
attiny26
attiny261
attiny261a
attiny28 [1]
attiny2313
attiny2313a
attiny40
attiny4313
attiny43u
attiny44
attiny44a
attiny441
attiny45
attiny461
attiny461a
attiny48
attiny828
attiny84
attiny84a
attiny841
attiny85
attiny861
attiny861a
attiny87
attiny88
attiny1634
Automotive AVR Devices:
atmega16m1
atmega32c1
atmega32m1
atmega64c1
atmega64m1
attiny167
ata5505
ata5272
ata5702m322
ata5782
ata5790
ata5790n
ata5831
ata5795
ata6612c
ata6613c
ata6614q
ata6616c
ata6617c
ata664251
CAN AVR Devices:
at90can32
at90can64
at90can128
LCD AVR Devices:
atmega169
atmega169a
atmega169p
atmega169pa
atmega329
atmega329a
atmega329p
atmega329pa
atmega3290
atmega3290a
atmega3290p
atmega3290pa
atmega649
atmega649a
atmega6490
atmega6490a
atmega6490p
atmega649p
Lighting AVR Devices:
at90pwm1
at90pwm2
at90pwm2b
at90pwm216
at90pwm3
at90pwm3b
at90pwm316
at90pwm161
at90pwm81
Smart Battery AVR Devices:
atmega8hva
atmega16hva
atmega16hva2
atmega16hvb
atmega16hvbrevb
atmega32hvb
atmega32hvbrevb
atmega64hve
atmega64hve2
atmega406
USB AVR Devices:
at90usb82
at90usb162
at90usb646
at90usb647
at90usb1286
at90usb1287
atmega8u2
atmega16u2
atmega16u4
atmega32u2
atmega32u4
atmega32u6
XMEGA Devices:
atxmega8e5
atxmega16a4
atxmega16a4u
atxmega16c4
atxmega16d4
atxmega32a4
atxmega32a4u
atxmega32c3
atxmega32c4
atxmega32d3
atxmega32d4
atxmega32e5
atxmega64a1
atxmega64a1u
atxmega64a3
atxmega64a3u
atxmega64a4u
atxmega64b1
atxmega64b3
atxmega64c3
atxmega64d3
atxmega64d4
atxmega128a1
atxmega128a1u
atxmega128a3
atxmega128a3u
atxmega128a4u
atxmega128b1
atxmega128b3
atxmega128c3
atxmega128d3
atxmega128d4
atxmega192a3
atxmega192a3u
atxmega192c3
atxmega192d3
atxmega256a3
atxmega256a3u
atxmega256a3b
atxmega256a3bu
atxmega256c3
atxmega256d3
atxmega384c3
atxmega384d3
Wireless AVR devices:
atmega644rfr2
atmega64rfr2
atmega128rfa1
atmega1284rfr2
atmega128rfr2
atmega2564rfr2
atmega256rfr2
Miscellaneous Devices:
at94K [2]
at76c711 [3]
at43usb320
at43usb355
at86rf401
at90scr100
ata6285
ata6286
ata6289
m3000 [4]
Classic AVR Devices:
at90s1200 [1]
at90s2313
at90s2323
at90s2333
at90s2343
at90s4414
at90s4433
at90s4434
at90s8515
at90c8534
at90s8535
Utilizza inoltre direttamente i Timers e, anche li, bisognerebbe vedere i nomi dei registri e i Timers utilizzabili.
Guglielmo
NON solo, ho visto il progetto che stai realizzando e c'è chiaramente scritto:
This circuit is attached to a 110-220 voltage.
Ora, da REGOLAMENTO, punto 15 e suoi sottopunti, qui NON è permesso parlare di tensioni oltre la bassissima tensione, per cui ... il thread viene chiuso.
@geppetto72 : per il futuro ti prego di prestare maggiore attenzione al rispetto del regolamento onde evitare altre possibili conseguenze. Grazie.
Guglielmo