Sostieni il forum con una donazione! Il tuo contributo ci aiuterà a rimanere online!
Immagine

Da Merlin un progettino con Arduino per Analizzatore

Gli strumenti per l'elettronica ed il DIY
Rispondi
Avatar utente
Kagliostro
Amministratore
Amministratore
Messaggi: 9633
Iscritto il: 03/12/2007, 0:16
Località: Prov. di Treviso

Da Merlin un progettino con Arduino per Analizzatore

Messaggio da Kagliostro » 16/03/2020, 18:14

Ho appena visto sul sito di Merlin che, sulla scia dell'U-Tracer, ha realizzato un analizzatore per valvole a basso costo basato su Arduino

Per coloro che ne capiscono della materia o fossero anche solo interessati a dare un'occhiata

ecco il link

http://www.valvewizard.co.uk/analyser.html

Magari i più smaliziati potrebbero riconoscere delle parti che si adatterebbero al vecchio e mai portato a termine

provavalvole elettronico di cui abbiamo discusso qui sul forum

Non sapete quanto mi dispiaccia non capirci nulla :ops:

:bye1: :bye1:

K

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 16/03/2020, 18:51

Grazie Franco!

Cerco anche di capire perchè abbia usato due Arduino Nano invece di un Arduino più performante come ingressi/uscite/calcolo/porte di comunicazione. Costi e reperibilità?

Stasera se riesco ti posto una breve spiegazione di cosa fa questo sistema. Ho visto alcune cose interessanti.

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 16/03/2020, 19:11

Ciao Franco, dividerò il codice a "blocchi" così che sia di semplice comprensione.

Il blocco qui sotto avvisa (#define) il microprocessore che utilizzerà le seguenti variabili (in maiuscolo).
Dopo il simbolo "//" c'è la spiegazione a chi legge il software di che cosa sia quella variabile.

Codice: Seleziona tutto

#define DIODE_MODE 1
#define TRIODE_MODE 2
#define PENTODE_MODE 3
#define MIN_HV_INCREMENT 5 //Minimum increment between each high-voltage datapoint in a sweep, in volts

#define MASTER 1            //For when hardware ID pin is high
#define SLAVE 0             //For when hardware ID pin is low

#define MASTER_ADDR 0x0A      //I2C Address of the MASTER Arduino
#define SLAVE_ADDR 0x0B       //I2C Address of the SLAVE Arduino
#define DAC1_ADDR 0x60  //I2C Address of one MCP4725, by default pin A0 is pulled to GND.
#define DAC2_ADDR 0x61   //I2C Address of other MCP4725; its pin A0 must be pulled HIGH to make address 0x61 (also remove pull-up resistors). Note that the breakout board uses the MCP4725A0.
//NB: I2C can send 32 ints per transmission.

#define HARDWARE_ID_PIN 12  //High for master, low for slave
#define VH_PIN A2           //Heater-voltage sense from buck regulator
#define IH_PIN A3           //Heater-current sense from buck regulator
#define PWM_PIN 6           //PWM drive signal to buck regulator MOSFET 
#define CHARGE1_PIN 8        //Drive to high-voltage charge MOSFET
#define DISCHARGE1_PIN 11     //Drive to high-voltage discharge MOSFET 
#define FIRE1_PIN 7          //Drive to 'apply high voltage' MOSFET 
#define VA1_PIN A6           //High voltage sense 1
#define VA2_PIN A7           //High voltage sense 2
#define IA1_HI_PIN A1        //Small anode-current sense (large sense resistance) 
#define IA1_LO_PIN A0        //Large anode-current sense (small sense resistance)
#define IA2_HI_PIN A3        //Small anode-current sense (large sense resistance) 
#define IA2_LO_PIN A2        //Large anode-current sense (small sense resistance)
#define DISCHARGE2_PIN 4
#define FIRE2_PIN 2
#define CHARGE2_PIN 3       
#define LV_DETECT_PIN 11  //Pin to detect if heater power supply is present

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 16/03/2020, 19:15

Qui si dice che bisogna caricare sull'Arduino le seguenti librerie, che non sono altro che sottoprogrammi che fanno determinate funzioni.
Per esempio, la libreria "math" è un po' come far laureare Arduino in matematica, e quindi chiedergli di eseguire determinati calcoli che altrimenti richiederebbero di "spiegargli" come fare, procedura lunga e non alla portata di tutti.

Codice: Seleziona tutto

#include <math.h>
#include <avr/pgmspace.h> 
#include <Wire.h>   //Include the Wire library to talk I2C

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 16/03/2020, 19:18

Qui definisce le variabili che utilizzerà nel programma per svolgere le sue funzioni, e ti dice il tipo di variabile:

Below is a list of the data types commonly seen in Arduino, with the memory size of each in parentheses after the type name. Note: signed variables allow both positive and negative numbers, while unsigned variables allow only positive values.

boolean (8 bit) - simple logical true/false
byte (8 bit) - unsigned number from 0-255
char (8 bit) - signed number from -128 to 127. The compiler will attempt to interpret this data type as a character in some circumstances, which may yield unexpected results
unsigned char (8 bit) - same as 'byte'; if this is what you're after, you should use 'byte' instead, for reasons of clarity
word (16 bit) - unsigned number from 0-65535
unsigned int (16 bit)- the same as 'word'. Use 'word' instead for clarity and brevity
int (16 bit) - signed number from -32768 to 32767. This is most commonly what you see used for general purpose variables in Arduino example code provided with the IDE
unsigned long (32 bit) - unsigned number from 0-4,294,967,295. The most common usage of this is to store the result of the millis() function, which returns the number of milliseconds the current code has been running
long (32 bit) - signed number from -2,147,483,648 to 2,147,483,647
float (32 bit) - signed number from -3.4028235E38 to 3.4028235E38. Floating point on the Arduino is not native; the compiler has to jump through hoops to make it work. If you can avoid it, you should. We'll touch on this later.

Codice: Seleziona tutto

/************************************************************
 * GLOBAL VARIABLES
 ************************************************************/
#define ARRAY_LENGTH 10         
int targetValues[ARRAY_LENGTH];   //Array to hold target values (array lenth must be less than 32 ints or 16 unsigned ints owing to I2C limit)
int measuredValues[ARRAY_LENGTH]; //Array to hold measured values (array lenth must be less than 32 ints or 16 unsigned ints owing to I2C limit)

int testMode = 0;
float heaterVolts = 0;
int dataPoints = 2;
int maxAnodeVolts = dataPoints * MIN_HV_INCREMENT;
float maxGridVolts1 = 0;
float voltsPerStep = 0;
int screenVolts = 0;
int ulPercent = 0;
float maxGridVolts2 = 0;
int duty_cycle = 0;      //Duty cycle of buck converter
boolean hardware;         //Will be set to 1 if hardware ID pin is high (MASTER), else 0 (SLAVE).

const char selectTestMessage[] PROGMEM = {"Select test mode:"};
const char diodeMessage[] PROGMEM = {"[Diode / double diode = 1;"};
const char triodeMessage[] PROGMEM = {"Triode / double triode = 2;"};
const char pentodeMessage[] PROGMEM = {"Tetrode / pentode = 3]"};
const char heaterVoltsMessage[] PROGMEM = {"Set heater to: [up to 24V]"};
const char voltsSymbol[] PROGMEM = {" V"};
const char sweepHV1Message[] PROGMEM = {"Sweep anode(s) from 0V up to: [up to 500V]"};
const char dataPointsMessage[] PROGMEM = {"Number of datapoints per sweep: [not less than 2]"};
const char gridBias1Message[] PROGMEM = {"Step primary grid(s) bias supply from 0V down to: [up to -60V]"};
const char stepSizeMessage[] PROGMEM = {"Step size:"};
const char HV2Message[] PROGMEM = {"Set secondary high voltage supply to: [up to 500V]"};
const char ulMessage[] PROGMEM = {"UL percent: [0% = full pentode; 100% = full triode] "};
const char percentSymbol[] PROGMEM = {" %"};
const char gridBias2Message[] PROGMEM = {"Set secondary grid bias supply to: [up to -60V]"};
const char runMessage[] PROGMEM = {"Run test? [y/n]"};
const char errorMessage[] PROGMEM = {"Error: Parameter out of range?"};
const char columnLabels[] PROGMEM = {"Vb1(V), HV1(V), Ia1(mA), Vb2(V), HV2(V), Ia2(mA),"};



//INDICES FOR BOTH ARRAYS
#define VH       0   //Heater voltage  [example: 12.6V = adc391   6.3V = adc195] 
#define IH       1   //Heater current
#define VG1      2  //Grid voltage 1  [example: 1V = dac60, 10V=dac605, 20V=dac1210, 30V=dac1815, 40V=dac2420, 50V=dac3020]
#define HV1      3   //Anode voltage 1 [example: 600V=3.97V=adc992   300V=1.98V=adc496    200V=0.76V=330   100V=0.381V=V=adc165]
#define IA_HI_1  4   //Anode current hi 1
#define IA_LO_1  5  //Anode current lo 1
#define VG2      6   //Grid voltage 2
#define HV2      7   //Anode voltage 2
#define IA_HI_2  8   //Anode current hi 2
#define IA_LO_2  9   //Anode current lo 2

/************************************************************   
*FUNCTION PROTOTYPES
************************************************************/
void setHeaterVolts();
void setGridVolts();
void chargeHighVoltages();
void print_arrays();
void send_to_slave();
void masterReceiveData(int howMany);
void request_from_slave();
void slaveReceiveData(int howMany);
void slaveAnswerRequest();
void printMeasuredValues(void);
void setTargetValue(int index, float volts);
void calculateSweepValues(int sweepArray1[], int sweepArray2[]);
int checkForUserErrors(void); //returns 1 if the user has entered valid test parameters, else 0
void doMeasurement(void);
void dischargeHighVoltages(void);
void getUserParameters(void);
void printMessage(const char *messageptr);
int getUserInstruction(void);//returns 1 if user request to run test, else 0

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 16/03/2020, 19:25

Questa parte avvia la comunicazione seriale sull'Arduino (quella che manda informazioni tramite USB al PC):

Codice: Seleziona tutto

/************************************************************
 * SETUP
 ************************************************************/
void setup() {
  Serial.begin(9600); //Setup serial interface
Imposta il pin HARDWARE_ID_PIN come ingresso senza pull-up:

Codice: Seleziona tutto

  pinMode(HARDWARE_ID_PIN, INPUT);
  //I2C SDA is on Arduino Nano pin A4 as standard
  //I2C SCL is on Arduino Nano pin A5 as standard. These pins need no further setup.
  //By default, analog input pins also need no setup
Dice ad Arduino di controllare il riferimento in tensione esterno per la conversione da analogico a digitale:

Codice: Seleziona tutto

  analogReference(EXTERNAL);                //Use external voltage reference for ADC
Interessante escamotage per accelerare il funzionamento dell'Arduino, sebbene alteri i tempi interni (da considerare se programmo dei ritardi)

Codice: Seleziona tutto

TCCR0B = (TCCR0B & 0b11111000) | 0x01;    //Configure Timer0 for internal clock, no prescaling (bottom 3 bits of TCCR0B)
                                            //Makes Arduino run 6.3 times faster than normal. NB: This affects Arduino delay() function!

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 16/03/2020, 19:29

Qui impostiamo un PWM come comando esterno e ripetiamo il segnale sul led dell'arduino per vedere che il risultato sia corretto (col PWM di valore alto il led si illumina maggiormente che non col PWM basso).

Codice: Seleziona tutto

analogWrite(PWM_PIN, 0);                  //Make sure PWM output is zero on startup
  pinMode(LED_BUILTIN, OUTPUT);             //Arduino built-in LED for debugging
Il codice è uguale su entrambi gli Arduino utilizzati, e tramite una configurazione esterna si dice al processore se è colui che comanda e "parla col pc", cioè il Master, oppure lo Slave.

Codice: Seleziona tutto

 hardware = digitalRead(HARDWARE_ID_PIN); //Identify if this is MASTER (1) or SLAVE (0) Arduino
  hardware = 1;
  if(hardware == MASTER){
      pinMode(CHARGE1_PIN, OUTPUT);  
      pinMode(DISCHARGE1_PIN, OUTPUT);
      pinMode(FIRE1_PIN, OUTPUT);
      pinMode(CHARGE2_PIN, OUTPUT);
      pinMode(DISCHARGE2_PIN, OUTPUT);
      pinMode(FIRE2_PIN, OUTPUT); 
      digitalWrite(FIRE1_PIN, LOW); 
      digitalWrite(FIRE2_PIN, LOW);       
      digitalWrite(CHARGE1_PIN, LOW);
      digitalWrite(CHARGE2_PIN, LOW);
      digitalWrite(DISCHARGE1_PIN, HIGH); //make sure capacitor banks are discharged ready for first sweep
      digitalWrite(DISCHARGE2_PIN, HIGH);
      Wire.begin(MASTER_ADDR);            //Register I2C address
      Wire.onReceive(masterReceiveData);  //Interrupt when I2C data is being received

  }
  else{ //else this is SLAVE hardware
      pinMode(LV_DETECT_PIN, INPUT);
      analogWrite(PWM_PIN, 0);            //Set heater to 0V at start-up
      Wire.begin(SLAVE_ADDR);             //Register I2C address
      Wire.onReceive(slaveReceiveData);   //Interrupt when I2C data is being received
      Wire.onRequest(slaveAnswerRequest); //Interrupt when master demands a response
  }

}

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 16/03/2020, 19:34

Suggerisco poi di saltare per ora questa parte qui sotto, che è il programma principale, e leggersi tutte le parti successive che sono molto ben commentate:

Codice: Seleziona tutto

/************************************************************
 * MAIN LOOP
 ************************************************************/
void loop() {

              
   if(hardware == MASTER){     
    
      static int runTest = 0;
      
      while(!runTest){
          getUserParameters();  //Ask for user input, returns 1 when ready
          runTest = checkForUserErrors(); //Returns 1 if no errors found
      }

      float sweepTable1[dataPoints];//Stores HV1 voltages to be used during a sweep
      float sweepTable2[dataPoints];//Stores HV2 voltages to be used during a sweep
      calculateSweepValues(sweepTable1, sweepTable2); //Populate the sweep values
      
      runTest = getUserInstruction(); //user must press 'y' to run test
      
               
   
      
    if(runTest){ //commence test
          setTargetValue(VH, heaterVolts); //send again in case anything has changed
          send_to_slave();
          printMessage(columnLabels);
          
          for(float j = 0; j <= maxGridVolts1; j += voltsPerStep){
              setTargetValue(VG1, j);
              if(testMode == TRIODE_MODE){//if testing a triode
                targetValues[VG2] = targetValues[VG1];//make VG2 supply the same as VG1 supply
              }
              else{ //else make it constant
                setTargetValue(VG2, maxGridVolts2);
              }

              if(maxGridVolts1 == 0){//if user requested only 0V curve
                j++;//stop the test from repeating
              }
              if(testMode == DIODE_MODE){//if testing a diode
                j = maxGridVolts1 + 1;//stop the test from repeating
              }
              
              setGridVolts();
              for(int i = 0; i < dataPoints; i++){
                  float nextHV1 = sweepTable1[i];//get next datapoint for HV1 sweep
                  float nextHV2 = sweepTable2[i];//get next datapoint for HV2 sweep
                  setTargetValue(HV1, nextHV1);
                  setTargetValue(HV2, nextHV2);
                  chargeHighVoltages();
                  doMeasurement();
                  request_from_slave(); 
                  printMeasuredValues();  
              }
              dischargeHighVoltages(); //sweep is complete
          }
   }
 
         digitalWrite(LED_BUILTIN, LOW); //for debugging
    }

    else{ //Else this is SLAVE hardware
            setHeaterVolts();
    }
 
} //End of main program loop

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 16/03/2020, 19:51

Prendo questa parte di programma per spiegare come si traduce un programma in Italiano, guardate questa immagine:
Immagine


Qui fornisce il titolo a cosa farà la parte successiva del programma, che si chiama chargeHighVoltages

Codice: Seleziona tutto

/****************************************************************************
* Charges up the high-voltage capacitor banks to the target values
****************************************************************************/
Dichiara (void) la funzione chargeHighVoltages

Codice: Seleziona tutto

void chargeHighVoltages(){ //Manages the HV supply
Spegne tutti i mosfet (buona pratica quando non si sa da quale funzione precedente si arriva

Codice: Seleziona tutto

    digitalWrite(FIRE1_PIN, LOW);                       //Turn off MOSFETs (fail-safe measure)
    digitalWrite(FIRE2_PIN, LOW);
    digitalWrite(CHARGE1_PIN, LOW);
    digitalWrite(CHARGE2_PIN, LOW);
    digitalWrite(DISCHARGE1_PIN, LOW);
    digitalWrite(DISCHARGE2_PIN, LOW);
Vedere il partitore di tensione che ha per uscita VA1, per esser sicuro di non eccedere mai i 5V sull'ingresso dell'Arduino:
Immagine

E vedere qui l'ingresso VA1 sull'Arduino Master:
Immagine

Legge le tensioni ricavate dallo schema precedente (VA1_PIN è appuntol'ingresso di VA1, stessa cosa fa per VA2):

Codice: Seleziona tutto

    measuredValues[HV1] = analogRead(VA1_PIN);         //Measure the high voltage and store the value
    measuredValues[HV2] = analogRead(VA2_PIN);         //Measure the high voltage and store the value
Non carica entrambi i gruppi di condensatori insieme, ma prima carica quelli relativi a HV1 controllando la tensione:

Codice: Seleziona tutto

    //While either storage cap is not charged to the correct voltage, alternately charge each cap
    //NB: Both cannot be charged simultaneously or one may hold down the supply to the other.
    while((measuredValues[HV1] != targetValues[HV1]) || (measuredValues[HV2] != targetValues[HV2])){   
        while(measuredValues[HV1] < (targetValues[HV1]-0)) {//If voltage is too low, charge capacitor
              digitalWrite(CHARGE1_PIN, HIGH); 
              measuredValues[HV1] = analogRead(VA1_PIN);    //Keep checking the voltage
        }
E quando è corretta isola i condensatori dal resto del circuito (vedere sempre prima immagine animata):

Codice: Seleziona tutto

        digitalWrite(CHARGE1_PIN, LOW); //Done, isolate this storage capacitance. It will begin to discharge slowly.
Ripete la stessa procedura per il secondo gruppo di condensatori di HV2:

Codice: Seleziona tutto

        measuredValues[HV2] = analogRead(VA2_PIN);          //Measure the high voltage and store the value
        while(measuredValues[HV2] < (targetValues[HV2]-0)) {//If voltage is too low, charge capacitor
              digitalWrite(CHARGE2_PIN, HIGH);
              measuredValues[HV2] = analogRead(VA2_PIN);    //Keep checking the voltage
        }
        digitalWrite(CHARGE2_PIN, LOW); //Done, isolate this storage capacitance. It will begin to discharge slowly.
Controlla di nuovo per sicurezza i condensatori del primo banco HV1, che non si siano scaricati nel frattempo.

Codice: Seleziona tutto

        measuredValues[HV1] = analogRead(VA1_PIN);//Check first capacitor bank again
    }

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 17/03/2020, 9:15

Piccola nota:
da questo progetto si può sviluppare un sistema che faccia il bias in automatico alle valvole finali ad ogni startup dell'amplificatore.

Avatar utente
Kagliostro
Amministratore
Amministratore
Messaggi: 9633
Iscritto il: 03/12/2007, 0:16
Località: Prov. di Treviso

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da Kagliostro » 17/03/2020, 11:10

Ma tu pensa

:cool1:

Grazie per la divulgazione Robi

Franco

Avatar utente
Kagliostro
Amministratore
Amministratore
Messaggi: 9633
Iscritto il: 03/12/2007, 0:16
Località: Prov. di Treviso

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da Kagliostro » 17/03/2020, 13:05

Chi ne capisce potrebbe postare un BOM dei materiali necessari per comporre l'analizzatore

corredato da una piccola descrizione su come vanno assemblati tra di loro per realizzare l'analizzatore

Grazie

K

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 15/04/2020, 18:34

Kagliostro ha scritto:
17/03/2020, 11:10
Grazie per la divulgazione Robi

Franco
Prego Franco,

spero aiuti altre persone ad interessarsi all'argomento e postare altri progetti sul forum!

Avatar utente
robi
Amministratore
Amministratore
Messaggi: 9481
Iscritto il: 17/12/2006, 13:57
Località: Alba

Re: Da Merlin un progettino con Arduino per Analizzatore

Messaggio da robi » 15/04/2020, 18:34

Kagliostro ha scritto:
17/03/2020, 13:05
Chi ne capisce potrebbe postare un BOM dei materiali necessari per comporre l'analizzatore
Sì, sarebbe una bella idea per chi ne avesse voglia!

Rispondi