Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

decodifica contraves decimale/binario

Progetti, interfacciamento, discussioni varie su questa piattaforma.

Moderatori: Foto UtenteWALTERmwp, Foto Utentexyz

0
voti

[1] decodifica contraves decimale/binario

Messaggioda Foto Utenteaduri » 11 feb 2022, 14:20

Buongiorno a tutti,
ho un problema da risolvere.

Sto cercando di simulare dei contraves (selettori decimali/binari) per comandare una scheda che gestisce un vfo di una radio con arduino.

La frequenza dovrà variare da 1 MHz a 30MHz e la risoluzione a 100Hz quindi se il valore fosse rx=30.000.000Hz andrà troncata ai 100Hz quindi rx=rx/100.
Otterrò quindi 300.000 per gestire i 6 contraves.

La mia idea sarebbe quella di creare una funzione

Codice: Seleziona tutto
void converti(long fr) {   // Funzione per scomporre le cifre.

  f=fr%10;  //100hz
  fr=fr/10;
  e=fr%10;  //1Khz
  fr=fr/10;
  d=fr%10;  //10Khz
  fr=fr/10;
  c=fr%10;  //100Khz
  fr=fr/10;
  b=fr%10;  //1MHz
  fr=fr/10;
  a=fr%10;  //10MHz
  }


Ed una seconda funzione con maschera per inviare il codice binario relativo per simulare i contraves dove i vari a,b,c,d,e,f rappresentano i 6 contraves
ed 0/1/2/4 rappresentano gli esponenti base 2 del valore binario che piloteranno i 4 pin in ingresso nella scheda :

Codice: Seleziona tutto
void inviaBCD(){
 
  digitalWrite(f0, (HIGH &&(f & B0001)));   // 100hz
  digitalWrite(f1, (HIGH &&(f & B0010)));   
  digitalWrite(f2, (HIGH &&(f & B0100)));   
  digitalWrite(f4, (HIGH &&(f & B1000)));   
 
  digitalWrite(e0, (HIGH &&(e & B0001)));   // 1Khz
  digitalWrite(e1, (HIGH &&(e & B0010)));   
  digitalWrite(e2, (HIGH &&(e & B0100)));   
  digitalWrite(e4, (HIGH &&(e & B1000)));   
 
  digitalWrite(d0, (HIGH &&(d & B0001)));   // 10Khz
  digitalWrite(d1, (HIGH &&(d & B0010)));   
  digitalWrite(d2, (HIGH &&(d & B0100)));   
  digitalWrite(d4, (HIGH &&(d & B1000)));   

  digitalWrite(c0, (HIGH &&(c & B0001)));   // 100Khz
  digitalWrite(c1, (HIGH &&(c & B0010)));   
  digitalWrite(c2, (HIGH &&(c & B0100)));   
  digitalWrite(c4, (HIGH &&(c & B1000)));
 
  digitalWrite(b0, (HIGH &&(b & B0001)));   // 1Mhz
  digitalWrite(b1, (HIGH &&(b & B0010)));   
  digitalWrite(b2, (HIGH &&(b & B0100)));   
  digitalWrite(b4, (HIGH &&(b & B1000)));   
 
  digitalWrite(a0, (HIGH &&(a & B0001)));   // 10Mhz
  digitalWrite(a1, (HIGH &&(a & B0010)));     

                }

Simulandolo con Excel queste 2 funzioni girano ottimamente ma con arduino da dei risultati incongruenti.


Ho recuperato un sw di gestione encoder con display lcd seriale per gestire questa variabile che andrà convertita in binaria.

Questa routine è stata presa in rete (autore Richard Visokey AD7C - www.ad7c.com) e gestiva un ad9850 (DDS) per produrre una frequenza, perfettamente funzionante
solo qualche piccolo salto di frequenza dovuto ai contatti di questi encoder meccanici economici.

Codice: Seleziona tutto
// Include the library code
#include <LiquidCrystal.h>
#include <rotary.h>
#include <EEPROM.h>

//Setup some items
digitalWrite(pin, LOW); }

Rotary r = Rotary(2,3);
// sets the pins the rotary encoder uses. 
//Must be interrupt pins.

LiquidCrystal lcd(12, 13, 7, 6, 5, 4);

int_fast32_t rx=7200000; // Starting frequency of VFO
int_fast32_t rx2=1; // variable to hold the updated frequency
int_fast32_t increment = 10;
// starting VFO update increment in Hz.
int buttonstate = 0;
String hertz = "10 Hz";
int  hertzPosition = 5;
byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ;  //Placeholders

String freq; // string to hold the frequency

int_fast32_t timepassed = millis();
// int to hold the arduino miilis since startup

int memstatus = 1; 
// value to notify if memory is current or old. 0=old, 1=current.

int ForceFreq = 1;  // Change this to 0 after you upload and run a working sketch to activate the EEPROM memory.  YOU MUST PUT THIS BACK TO 0 AND UPLOAD THE SKETCH AGAIN AFTER STARTING FREQUENCY IS SET!

void setup() {
  pinMode(A0,INPUT); // Connect to a button that goes to GND on push
  digitalWrite(A0,HIGH);
  lcd.begin(16, 2);
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();

  lcd.setCursor(hertzPosition,1);   
  lcd.print(hertz);
   // Load the stored frequency 
  if (ForceFreq == 0) {
    freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6));
    rx = freq.toInt(); 
  }
}


void loop() {
  if (rx != rx2){   
        showFreq();
        sendFrequency(rx);
        rx2 = rx;
      }
     
  buttonstate = digitalRead(A0);
  if(buttonstate == LOW) {
        setincrement();       
    };

  // Write the frequency to memory if not stored and 2 seconds have passed since the last frequency change.
    if(memstatus == 0){   
      if(timepassed+2000 < millis()){
        storeMEM();
        }
      }   
}


ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if (result) {   
    if (result == DIR_CW){rx=rx+increment;}
    else {rx=rx-increment;};       
      if (rx >=30000000){rx=rx2;}; // UPPER VFO LIMIT
      if (rx <=1000000){rx=rx2;}; // LOWER VFO LIMIT
  }
}

void setincrement(){
  if(increment == 10){increment = 50; hertz = "50 Hz"; hertzPosition=5;}
  else if (increment == 50){increment = 100;  hertz = "100 Hz"; hertzPosition=4;}
  else if (increment == 100){increment = 500; hertz="500 Hz"; hertzPosition=4;}
  else if (increment == 500){increment = 1000; hertz="1 kHz"; hertzPosition=6;}
  else if (increment == 1000){increment = 2500; hertz="2.5 kHz"; hertzPosition=4;}
  else if (increment == 2500){increment = 5000; hertz="5 kHz"; hertzPosition=6;}
  else if (increment == 5000){increment = 10000; hertz="10 kHz"; hertzPosition=5;}
  else if (increment == 10000){increment = 100000; hertz="100 kHz"; hertzPosition=4;}
  else if (increment == 100000){increment = 1000000; hertz="1 MHz"; hertzPosition=6;} 
  else{increment = 10; hertz = "10 Hz"; hertzPosition=5;}; 
   lcd.setCursor(0,1);
   lcd.print("                ");
   lcd.setCursor(hertzPosition,1);
   lcd.print(hertz);
   delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed.
};

void showFreq(){
    millions = int(rx/1000000);
    hundredthousands = ((rx/100000)%10);
    tenthousands = ((rx/10000)%10);
    thousands = ((rx/1000)%10);
    hundreds = ((rx/100)%10);
    tens = ((rx/10)%10);
    ones = ((rx/1)%10);
    lcd.setCursor(0,0);
    lcd.print("                ");
   if (millions > 9){lcd.setCursor(1,0);}
   else{lcd.setCursor(2,0);}
    lcd.print(millions);
    lcd.print(".");
    lcd.print(hundredthousands);
    lcd.print(tenthousands);
    lcd.print(thousands);
    lcd.print(".");
    lcd.print(hundreds);
    lcd.print(tens);
    lcd.print(ones);
    lcd.print(" MHz  ");
    timepassed = millis();
    memstatus = 0; // Trigger memory write
};

void storeMEM(){
  //Write each frequency section to a EPROM slot.  Yes, it's cheating but it works!
   EEPROM.write(0,millions);
   EEPROM.write(1,hundredthousands);
   EEPROM.write(2,tenthousands);
   EEPROM.write(3,thousands);
   EEPROM.write(4,hundreds);       
   EEPROM.write(5,tens);
   EEPROM.write(6,ones);   
   memstatus = 1;  // Let program know memory has been written
};



Durante la fase di decodifica dandogli in pasto la variabile rx succede che già dalla prima funzione i dati non tornano.

Credo sia un problema di variabili ma non riesco ad uscirne.

Premetto che non sono un programmatore ma prendo pezzi funzionanti qua e là e cerco di adattarli alle mie esigenze.

Scusate la lungaggine ma penso che possa essere utile anche ad altri.

grazie per chi avrà la pazienza di analizzare questi codici.

ciao
Antonio
Avatar utente
Foto Utenteaduri
435 1 5 11
Expert
Expert
 
Messaggi: 937
Iscritto il: 29 giu 2005, 23:13
Località: Genova

0
voti

[2] Re: decodifica contraves decimale/binario

Messaggioda Foto UtenteMarcoD » 11 feb 2022, 15:50

ed 0/1/2/4 rappresentano gli esponenti base 2 del valore binario che piloteranno i 4 pin in ingresso nella scheda :
? gli esponenti dovrebbero essere 0,1,2,3 corrispondenti a 1,2,4,8.

Esaminare i programmi altrui è molto faticoso, al momento non mi sento di farlo.
Anni fa avevo scritto qualcosa di simile, era brutto ma funzionante.
La routine scompone un numero intero di 4 cifre nei caratteri ASCII corrispondenti.
Non sommando la base 48 rimane un byte numero BCD che forse corrisponde alla codifica (8,4,2,1) della cifra contraves corrispondente.
Prova a leggere la funzione allegata per capire come funziona e trarre ispirazione per il tuo programma.

Codice: Seleziona tutto
//funzione converte un numero intero max 9999 nei 4 caratteri ascii corrispondenti
// il risultato avviene tramite puntatore    31/5/09
void intasc1(int num, char *na, int nc,int np)
{
// variabili locali usate dalla funzione:
// nc numero cifre da 2 a 4; np posizione virgola da 0 a 3 prima della ultima cifra
boolean cifrasignif = false;
int nummigl; int numcent; int numdeci; int numunit; int nummiglper1000; int numcentper100; int numero;
numero = num; // il dato in ingresso non viene modificato
if (numero > 9999) { numero = 9999;}
if (numero < 0) { numero = 0;}
int ic = 0 ; //indice cifra 
cifrasignif = false;
nummigl = numero/1000;nummiglper1000 = nummigl*1000;
if (nummigl == 0) { na[ic]=32;ic++;} // forza il carattere spazio ( 32 in ASCII)
else
{ na[ic]=nummigl + 48; ic++; //carica la cifra da 0 a 9 in ASCII
cifrasignif = true;//la cifra è significativa
}
if (np == 3) { na[ic]= 44 ; ic++;}  //44 virgola; 46 punto
numcent = (numero-nummiglper1000)/100; numcentper100 = numcent*100;
if (numcent == 0)
{     if (cifrasignif == false) { na[ic]=32;ic++;} else { na[ic]=48;ic++; } }
else
{  na[ic] = numcent + 48; ic++; cifrasignif = true;}

if (np == 2) { na[ic]= 44 ; ic++;}  //44 virgola; 46 punto
numdeci = (numero-nummiglper1000-numcentper100)/10;
if (numdeci == 0)
{     if (cifrasignif == false) {  na[ic]=32; ic++; } else { na[ic]=48;ic++; } }
else
{  na[ic] = numdeci + 48;ic++;}
if (np == 1) { na[ic]= 44 ; ic++;}  //44 virgola; 46 punto
//la cifra delle unità viene sempre scritta
numunit = (numero-nummiglper1000-numcentper100-numdeci*10); na[ic] = numunit + 48;
}
Avatar utente
Foto UtenteMarcoD
12,2k 5 9 13
Master EY
Master EY
 
Messaggi: 6696
Iscritto il: 9 lug 2015, 16:58
Località: Torino

0
voti

[3] Re: decodifica contraves decimale/binario

Messaggioda Foto Utenteaduri » 11 feb 2022, 16:19

Grazie MarcoD della risposta,


? gli esponenti dovrebbero essere 0,1,2,3 corrispondenti a 1,2,4,8.


infatti 2^0 =1, 2^1=2, 2^2=4 e 2^3=8

quindi in binario 0000, 0001, 0010, 0100

guarderò il tuo codice con interesse.

ciao
Antonio
Avatar utente
Foto Utenteaduri
435 1 5 11
Expert
Expert
 
Messaggi: 937
Iscritto il: 29 giu 2005, 23:13
Località: Genova


Torna a Arduino

Chi c’è in linea

Visitano il forum: Nessuno e 8 ospiti