Jump to content
ELFORUM - Forumul electronistilor

Migrare Arduino pe ATmega328P ?


messu
 Share

Recommended Posts

Posted (edited)

A incercat cineva sa faca asa ceva ?

Eu incerc sa realizez priectul de aici https://www.hfsignals.com/index.php/antuino/

Inainte de a trece la relizarea cablajelor, am facut proba sa vad daca totul functioneaza. Si, desi pe Arduino (am folosit un Nano) totul este in regula, cand am trecut pe ATmega 328p, treaba NU PREA mai functioneaza, sau nu functioneaza in totalitate.

In speta, interfata grafica este in regula, encoderul functioneaza, insa nu mai citeste nimic pe ADC. 

Cu proiectul rulat pe Nano, cu un potentiometru legat pe ADC, se vad clar variatiile la actionarea potentiometrului. Cand mut acelasi hex pe ATmega328, nu mai citeste nimic. 

Care ar putea fi cauza ?

Stiu ca varianta TQFP32 are doua ADC-uri in plus fata de DIP28. Trebuiesc facute modificari in cod pentru asta, in afara de  realocarea porturilor (pe care bineinteles ca am facut-o in concordanta cu schema atasata)?


//to switch on/off various clocks
#define SI_CLK0_CONTROL  16      // Register definitions
#define SI_CLK1_CONTROL 17
#define SI_CLK2_CONTROL 18

#define IF_FREQ  (24993000l)
#define MODE_ANTENNA_ANALYZER 0
#define MODE_MEASUREMENT_RX 1
#define MODE_NETWORK_ANALYZER 2
unsigned long mode = MODE_ANTENNA_ANALYZER;

char b[32], c[32], serial_in[32];
int return_loss;
unsigned long frequency = 10000000l;
int openHF = 96;
int openVHF = 96;
int openUHF = 68;

#define DBM_READING (A3) //A6 initial
int dbmOffset = -114;

int menuOn = 0;
unsigned long timeOut = 0;


/*
 * The return loss in db to vswr look up.
 * The VSWR is stored as multiplied by 10, i.e. VSWR of 1.5 is stored as 15
 */
const int PROGMEM vswr[] = {
999,  // 0 db
174,  // 1 db
87,   // 2 db
58,   // 3 db
40,   // 4 db
35,   // 5 db
30,   // 6 db
26,   // 7 db
20,   // 8 db
19,   // 9 db
18,   // 10 db
17,   // 11 db
16,   // 12 db
15,   // 13 db
14,   // 14 db
14,   // 15 db
14,   // 16 db
13,   // 17 db
13,   // 18 db
12,   // 19 db
12,   // 20 db
12,   // 21 db
12,   // 22 db
11,   // 23 db
11,   // 24 db
11,   // 25 db
11,   // 26 db
10,   // 27 db
10,   // 28 db 
10,   // 29 db
10    // 30 db
};


/*
 * The return loss in db to vswr look up.
 * The VSWR is stored as multiplied by 10, i.e. VSWR of 1.5 is stored as 15
 */
const int PROGMEM vswr_lin[] = {
999,  // 0 db
174,  // 1 db
87,   // 2 db
58,   // 3 db
44,   // 4 db
35,   // 5 db
30,   // 6 db
26,   // 7 db
23,   // 8 db
20,   // 9 db
19,   // 10 db
17,   // 11 db
17,   // 12 db
16,   // 13 db
15,   // 14 db
14,   // 15 db
14,   // 16 db
13,   // 17 db
13,   // 18 db
12,   // 19 db
12,   // 20 db
12,   // 21 db
12,   // 22 db
11,   // 23 db
11,   // 24 db
11,   // 25 db
11,   // 26 db
10,   // 27 db
10,   // 28 db 
10,   // 29 db
10    // 30 db
};

const int PROGMEM db_distortion[] = {
};



void active_delay(int delay_by){
  unsigned long timeStart = millis();

  while (millis() - timeStart <= delay_by) {
      //Background Work      
  }
}

int tuningClicks = 0;
int tuningSpeed = 0;

void updateDisplay(){
  sprintf(b, "%ldK, %ldK/div", frequency/1000, spanFreq/10000); 
  GLCD.DrawString(b, 20, 57);
}

int calibrateClock(){
  int knob = 0;
  int32_t prev_calibration;
  char  *p;

  GLCD.ClearScreen();
  GLCD.DrawString("1. Monitor RF Out", 0, 0);
  GLCD.DrawString("  port on 10 MHz freq.", 0, 10);
  GLCD.DrawString("2. Tune to zerbeat and", 0, 20);
  GLCD.DrawString("3. Click to Save", 0, 30);

  GLCD.DrawString("Save", 64, 45);
  GLCD.DrawRect(60,40,35,20);


  //keep clear of any previous button press
  while (btnDown())
    active_delay(100);
  active_delay(100);

  prev_calibration = xtal_freq_calibrated;
  xtal_freq_calibrated = 27002000l;

  si5351aSetFrequency_clk0(10000000l);  
  ltoa(xtal_freq_calibrated - 27000000l, c, 10);
  GLCD.FillRect(0,40,50,15, WHITE);
  GLCD.DrawString(c, 4, 45);     

  while (!btnDown())
  {
    knob = enc_read();

    if (knob > 0)
      xtal_freq_calibrated += 10;
    else if (knob < 0)
      xtal_freq_calibrated -= 10;
    else 
      continue; //don't update the frequency or the display

    si5351aSetFrequency_clk0(10000000l);  
      
    ltoa(xtal_freq_calibrated - 27000000l, c, 10);
    GLCD.FillRect(0,40,50,15, WHITE);
    GLCD.DrawString(c, 4, 45);     
  }

  while(btnDown())
    delay(100);
  delay(100);
  GLCD.ClearScreen();
  GLCD.DrawString("Calibration Saved", 0, 25);

  EEPROM.put(MASTER_CAL, xtal_freq_calibrated);
  delay(2000);
}

int readOpen(unsigned long f){
  int i, r;

  takeReading(f);
  delay(100);
  r = 0;
  for (i = 0; i < 10; i++){
    r += analogRead(DBM_READING)/5;
    delay(50);
  }
  //debug the open reading
  sprintf(c, "%04d", r);
  GLCD.DrawString(c, 0, 42);

  delay(1000);
  
  return (r+5)/10;
}

int calibrateMeter(){
  
  GLCD.ClearScreen();
  GLCD.DrawString("Disconnect Antenna", 0, 0);
  GLCD.DrawString("port and press Button", 0, 10);
  GLCD.DrawString("to calibrate SWR", 0, 20);
  GLCD.DrawString("OK", 10, 42);
  GLCD.DrawRect(5,35,20,20);
    
  //wait for a button down
  while(!btnDown())
    active_delay(50);

  GLCD.ClearScreen();
  GLCD.DrawString("Calibrating.....", 10, 25);
  delay(1000);
  
  int i, r;
  mode = MODE_ANTENNA_ANALYZER;
  delay(100);
  r = readOpen(20000000l);
  Serial.print("open reading of HF is ");Serial.println(r);
  EEPROM.put(OPEN_HF, r);

  r = readOpen(140000000l);
  Serial.print("open reading of VHF is ");Serial.println(r);
  EEPROM.put(OPEN_VHF, r);

  r = readOpen(440000000l);
  Serial.print("open reading of UHF is ");Serial.println(r);
  EEPROM.put(OPEN_UHF, r);
  
  menuOn = 0;
 
  GLCD.ClearScreen();
  GLCD.DrawString("Done!",10,25);
  delay(1000);
  
  //switch off just the tracking source
  si5351aOutputOff(SI_CLK0_CONTROL);
  takeReading(centerFreq);
  updateDisplay();
}

int openReading(unsigned long f){
  if (f < 60000000l)
    return openHF;
  else if (f < 150000000l)
    return openVHF;
  else
    return openUHF;
}

long prev_freq = 0; //this is used only inside takeReading, it should have been static local
int prevMode = 0;
void takeReading(long newfreq){
  long local_osc;

  if (newfreq < 20000l)
      newfreq = 20000l;
  if (newfreq < 150000000l)
  {
    if (newfreq < 50000000l)
      local_osc = newfreq + IF_FREQ;
    else
      local_osc = newfreq - IF_FREQ;
  } else {
    newfreq = newfreq / 3;
    local_osc = newfreq - IF_FREQ/3;
  }

  if (prev_freq != newfreq || prevMode != mode){
    switch(mode){
    case MODE_MEASUREMENT_RX:
      si5351aSetFrequency_clk2(local_osc);
      si5351aOutputOff(SI_CLK1_CONTROL);
      si5351aOutputOff(SI_CLK0_CONTROL);
    break;
    case MODE_NETWORK_ANALYZER:
      si5351aSetFrequency_clk2(local_osc);
      si5351aOutputOff(SI_CLK1_CONTROL);        
      si5351aSetFrequency_clk0(newfreq);
    break;
    default:
      si5351aSetFrequency_clk2(local_osc);  
      si5351aSetFrequency_clk1(newfreq);
      si5351aOutputOff(SI_CLK0_CONTROL);        
    }      
    prev_freq = newfreq;
    prevMode = mode;
//    Serial.print(mode);Serial.print(':');
//    Serial.println(prev_freq);
  }     
}

void setup() {
  GLCD.Init();            
  GLCD.SelectFont(System5x7);
  
  Serial.begin(9600);
  b[0]= 0;

  Wire.begin();
  Serial.begin(9600);
  Serial.flush();  
  Serial.println(F(" RF Antuino v2.1"));
  analogReference(DEFAULT);

  unsigned long last_freq = 0;
  EEPROM.get(MASTER_CAL, xtal_freq_calibrated);
  EEPROM.get(LAST_FREQ, last_freq);
  EEPROM.get(OPEN_HF, openHF);
  EEPROM.get(OPEN_VHF, openVHF);
  EEPROM.get(OPEN_UHF, openUHF);
  EEPROM.get(LAST_SPAN, selectedSpan);
  EEPROM.get(LAST_MODE, mode);

  Serial.print("*hf_open:");
  Serial.println(openHF);
  //the openHF reading is actually -19.5 dbm
  dbmOffset = -23 - openHF;

  Serial.println(last_freq);
  if (0 < last_freq && last_freq < 500000000l)
      centerFreq = last_freq;

  if (xtal_freq_calibrated < 26900000l || xtal_freq_calibrated > 27100000l)
    xtal_freq_calibrated = 27000000l;

  if (mode < 0 || mode > 2)
    mode = 0;

  spanFreq = spans[selectedSpan];
  
  pinMode(ENC_A, INPUT_PULLUP);
  pinMode(ENC_B, INPUT_PULLUP);
  pinMode(FBUTTON, INPUT_PULLUP);


  if (btnDown()){
    calibration_mode();
  } else 
    updateScreen();
  
  si5351aOutputOff(SI_CLK0_CONTROL);
  takeReading(frequency);
  updateMeter();
}

int prev = 0;
void loop()
{
  doMenu();

 // doTuning2();
//  checkButton();

  int r = analogRead(DBM_READING);

  if (r != prev){
    takeReading(centerFreq);
    updateMeter();
    prev = r;
    Serial.println(r);
  }
  delay(50);   
}

 

antuino_digital.png

Edited by messu
Link to comment
Share on other sites

  • Replies 53
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

Posted (edited)
int16_t plot_readings[128];
#define Y_OFFSET 14

unsigned long f, f1, f2, stepSize;


int freq2screen(unsigned long freq){
  unsigned long f1, f2, hz_per_pixel;

  hz_per_pixel = spanFreq / 100;
  f1 = centerFreq - spanFreq/2;
  return (int)((freq - f1)/hz_per_pixel) + X_OFFSET;
}

int pwr2screen(int y){
  return  -y/2 + Y_OFFSET;
}

int vswr2screen(int y){
  if (y >= 100)
    y = 99;
  return y/2 + Y_OFFSET-1;
}

void setupPowerGrid(){
  int x, y;
  char p[20];

  GLCD.ClearScreen();  

  while(btnDown())
    delay(100);
    
  updateHeading();


  //sprintf(p, "%ldK, %ldK/div", centerFreq/1000, spanFreq/10000); 
  //GLCD.DrawString(p, 0, 57);

  //draw the horizontal grid
  for (y = -10; y >= -90; y-= 20){
    for (x = X_OFFSET; x <= 100+ X_OFFSET; x += 2)
      GLCD.SetDot(x,pwr2screen(y),BLACK);
  }

  //draw the vertical grid
  f1 = centerFreq - (spanFreq/2);
  f2 = centerFreq + (spanFreq/2);
  for (f = f1; f <= f2; f += spanFreq/10){
    for (y =0; y <= 50; y += 2)
      GLCD.SetDot(freq2screen(f),y+Y_OFFSET-2,BLACK);
  }

  for (y = -10; y >= -90; y-= 20){
    itoa(y, p, 10);
    GLCD.DrawString(p, 0, pwr2screen(y)-4);
  }  

}


void setupVSWRGrid(){
  int x, y;
  char p[20];

  GLCD.ClearScreen();  

  while(btnDown())
    delay(100);
    
  updateHeading();

  //draw the horizontal grid
  for (y = 0; y <= 100; y += 20){
    Serial.print("d");
    Serial.println(vswr2screen(y));
    for (x = X_OFFSET; x <= 100+ X_OFFSET; x += 2)
      GLCD.SetDot(x,vswr2screen(y),BLACK);
  }

  //draw the vertical grid
  f1 = centerFreq - (spanFreq/2);
  if (f1 < 0)
      f1 = 0;
  f2 = f1 + spanFreq;
  for (f = f1; f <= f2; f += spanFreq/10){
    Serial.print(f);
    Serial.print(",");
    Serial.println(freq2screen(f));
    for (y =0; y <= 50; y += 2)
      GLCD.SetDot(freq2screen(f),y+Y_OFFSET,BLACK);
  }

  for (y = Y_OFFSET; y < 100 + Y_OFFSET; y += 20){
    itoa(y/10, p, 10);
    strcat(p, ".");
    GLCD.DrawString(p, 0, vswr2screen(y)-8);
  }  

  f1 = centerFreq - (spanFreq/2);
  f2 = f1 + spanFreq;
  stepSize = (f2 - f1)/100;
  int i = 0, vswr_reading;

  Serial.print("f1 "); Serial.println(f1);
  Serial.print("f2 "); Serial.println(f2);
  Serial.print("step "); Serial.println(stepSize);

  for (f = f1; f < f2; f += stepSize){
    takeReading(f);
    delay(20);
    //now take the readings
    return_loss = openReading(f) - analogRead(DBM_READING)/5;
    if (return_loss > 30)
      return_loss = 30;
    if (return_loss < 0)
      return_loss = 0;
    
    vswr_reading = pgm_read_word_near(vswr + return_loss);
    plot_readings[i] = vswr_reading;
    //Serial.print(vswr_reading); Serial.print(' '); Serial.print(f); Serial.print(' ');Serial.print(freq2screen(f)); 
    //Serial.print("x");Serial.print(vswr_reading);Serial.print(' ');Serial.println(vswr2screen(vswr_reading));

    if (i == 0)
      GLCD.SetDot(freq2screen(f),vswr2screen(vswr_reading),BLACK);
    else
      GLCD.DrawLine(i + X_OFFSET-1, vswr2screen(plot_readings[i-1]), i + X_OFFSET, vswr2screen(plot_readings[i])); 
    i++;
  }

  int current_pos = 50;

  powerHeading(current_pos);
  while (!btnDown()){
    i = enc_read();
    
    if ((i < 0 && current_pos + i >= 0) || 
      (i > 0 && current_pos + i <= 100)){
      current_pos += i;
      powerHeading(current_pos); 
    }
  }
  
  while(btnDown())
    delay(100);
}

void updateCursor(int pos, char*text){
  GLCD.FillRect(0,0,127,10, WHITE);
  GLCD.DrawString(text, 0, 0);
  GLCD.DrawLine(pos+ X_OFFSET, 8, pos + X_OFFSET,9);
}


void powerHeading(int current_pos){
  
  GLCD.FillRect(0,0,127,12, WHITE);
  freqtoa(f1 + (stepSize * current_pos), b);
  GLCD.DrawString(b, 0, 0);
  
  if (mode == MODE_ANTENNA_ANALYZER)
    sprintf (b, " %d.%01d", plot_readings[current_pos]/10,plot_readings[current_pos] % 10);
  else
    sprintf(b, "%ddbm", plot_readings[current_pos]);

  GLCD.DrawString(b, 80, 0);
  GLCD.DrawLine(current_pos+ X_OFFSET, 8, current_pos + X_OFFSET,11);
}

void plotPower(){
  int x, y, pwr;
  char p[20];

  GLCD.ClearScreen();  

  while(btnDown())
    delay(100);
    
  //draw the horizontal grid
  for (y = 0; y <= 100; y += 20){
    Serial.print("d");
    Serial.println(pwr2screen(y));
    for (x = X_OFFSET; x <= 100+ X_OFFSET; x += 2)
      GLCD.SetDot(x,vswr2screen(y),BLACK);
  }

  //draw the vertical grid
  f1 = centerFreq - (spanFreq/2);
  if (f1 < 0)
      f1 = 0;
  f2 = f1 + spanFreq;
  for (f = f1; f <= f2; f += spanFreq/10){
    for (y =0; y <= 50; y += 2)
      GLCD.SetDot(freq2screen(f),y+Y_OFFSET,BLACK);
  }


  for (y = -80; y <= -20; y += 20){
    itoa(y, p, 10);
    GLCD.DrawString(p, 0, pwr2screen(y)-4);
  }

  f1 = centerFreq - (spanFreq/2);
  f2 = f1 + spanFreq;
  stepSize = (f2 - f1)/100;
  int i = 0, vswr_reading;

  for (f = f1; f < f2; f += stepSize){
    takeReading(f);
    delay(50);
    //now take the readings
    analogRead(DBM_READING);
    analogRead(DBM_READING);
    analogRead(DBM_READING);
    
    int r = analogRead(DBM_READING)/5 + dbmOffset;
    plot_readings[i] = r;
    Serial.print(plot_readings[i]);
    Serial.print('-');
 
    if (i == 0)
      GLCD.SetDot(X_OFFSET, pwr2screen(plot_readings[i]),BLACK);
    else
      GLCD.DrawLine(i + X_OFFSET-1, pwr2screen(plot_readings[i-1]), i + X_OFFSET, pwr2screen(plot_readings[i])); 
    i++;
  }

  int current_pos = 50;

  powerHeading(current_pos);
  while (!btnDown()){
    i = enc_read();
    
    if ((i < 0 && current_pos + i >= 0) || 
      (i > 0 && current_pos + i <= 100)){
      current_pos += i;
      powerHeading(current_pos);

/*      GLCD.FillRect(0,0,127,12, WHITE);

      freqtoa(f1 + (stepSize * current_pos), p);
      GLCD.DrawString(p, 0, 0);
      sprintf(p, "%ddbm", plot_readings[current_pos]);
      GLCD.DrawString(p, 80, 0);
      GLCD.DrawLine(current_pos+ X_OFFSET, 8, current_pos + X_OFFSET,11); */
    }
  }
  
  while(btnDown())
    delay(100);
}

Da, AVcc, este conectat la 5V.

Am facut modificarea sugerata, dar, acum, la complilare, primesc urmatoarea eroare:

'DBM_READING' was not declared in this scope

 

si este indicata o linie din tab-ul plot al Arduino Sketch (proiectul are 5 tab-uri: antenna_ analyzer_p3, gui, ks0108_Arduino.h, plot , si5351
 

Edited by messu
Link to comment
Share on other sites

Posted (edited)

In schema din topic aveti legat la pinii A3 si A2 un encoder.
Nu se poate folosi pinul A3 si in alt scop, in plus are si pull up activat.
Folositi A6 cu arduino nano sau folosiți pinul A2 si mutati butonul encoderului pe alt pin, unul digital.
 

Edited by Elison
Link to comment
Share on other sites

Encoderul l-am mutat deja pe Ai si A2, iar butonul encoderului pe D0.

In aceasta configuratie functioneaza pe Arduino Nano, dar nu si pe Atmega 328p.

Vreau sa fac aceasta modificare pentru ca am o gramada de Atmega la dispozitie (nu si Arduino) si pe varianta DIP28 nu mai am alti pini la dispozitie.

Am sa fac modificarea sugerata de @nico_2010 si revin cu rezultatul.

Ma intriga faptul ca  acelasi cod nu merge pe doua microcontrolere "identice"...

Link to comment
Share on other sites

Acum 16 minute, messu a spus:

Ma intriga faptul ca  acelasi cod nu merge pe doua microcontrolere "identice"...

Da, este ciudat. Nu am intalnit aceasta situatie decat atunci cand fuse bits nu au fost setati corespunzator in Atmega328. Dar problema era legata de frecventa ceasului procesorului nu de rularea rutinelor din sketch.

Cum faci programarea Atmega328? Nu intreb pentru ca as vrea sa te invat eu ceva, sunt curios.

Link to comment
Share on other sites

Am un programator AVR-USB. 

Dar am incercat si cu "Arduino as ISP" insa cu acelasi rezultat.

Am incercat pe 3 microcontrolere diferite si la fel face...

Link to comment
Share on other sites

Programatorul este USBASP, probabil.

Un sfat: pune Atmega328 in programator si deschizi AVRDUDESS sau alt soft care stie sa citeasca fuses. Vezi ce citeste.

Apoi in Arduino IDE la board alege Arduino UNO si apoi Burn bootloader. Te vei asigura astfel ca ai setat fuses pentru frecventa ceas extern 16MHz.

Apoi schimbi board Atmega328 si Export compiled Binary. In folderul unde ai sketch-ul in format ino vei avea doua fisiere hex, unul cu bootloade altul fara.

Te muti iarasi in AVRDUDESS si citesti fuses si vei vedea diferenta. Acum programezi Atmega328 fara sa mai umbli la fuse bits. 

Link to comment
Share on other sites

Acum 7 ore, nico_2010 a spus:

OK, am scapat din vedere ca trebuia sa-ti spun sa inlocuiesti analogPin cu DBM_READING, adica:

int DBM_READING = A3;

Sper ca acum m-am exprimat mai clar. 

Am facut modificarea, dar nu se schimba nimic...:nerv

Link to comment
Share on other sites

Ceva similar am încercat să îi sugerez și eu. Am bănuiala că de fapt nu este o problemă de soft ci o problema cu frecvența procesorului. Nativ Atmega328 rulează la 1MHz și softul se blochează la o rutină care cere putere de calcul mare. 

Nu sunt eu mare specialist, dar nu am întâlnit până acum un soft care să ruleze pe Arduino UNO/NANO și să nu ruleze pe Atmega328. Dacă a respectat cerințele Arduino minimal când a făcut schema și a alocat pinii corect, trebuie sa meargă. 

Link to comment
Share on other sites

Mulțumesc pentru sugestii. Am sa fac și treabă cu citirea și compararea fisebitilor, însă ceasul cred că este setat corect. Dacă scot quart-ul din circuit, nu mai merge nimic. Am găsit ieri un Arduino Pro Mini, prin cutiile cu de toate și am să incerc și cu el sa vad ce se întâmplă. Arduino UNO, n-am...

Link to comment
Share on other sites

Acum 19 minute, messu a spus:

ceasul cred că este setat corect.

Eu m-am lovit de problema asta folosind Arduino IDE și programator USBASP. Deși în IDE selectam Atmega328 și ceas de 16MHz, softul rula foarte lent. Citind fuses din Atmega328 cu AVRDUDESS am avut surpriza să fie setați default, adică ceas de 1MHz. Procedând cum am descris totul a fost în regula. 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share




×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines