Sari la conținut
ELFORUM - Forumul electronistilor

Migrare Arduino pe ATmega328P ?


messu

Postări Recomandate

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

Editat de messu
Link spre comentariu
  • Răspunsuri 95
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • messu

    18

  • daniels

    15

  • nico_2010

    15

  • Marin1960

    11

Top autori în acest subiect

Imagini postate

Incearca asta:

int analogPin = A3;

in loc de asta:

#define DBM_READING (A3) //A6 initial

Si inca ceva: AVcc este conectat la 5V? In caz contrar, convertorul ADC nu va functiona.

Link spre comentariu
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
 

Editat de messu
Link spre comentariu

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. 

Link spre comentariu

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.
 

Editat de Elison
Link spre comentariu

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 spre comentariu
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 spre comentariu

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 spre comentariu

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 spre comentariu

Edit:

Daca vrei ulterior sa accesezi Atmega prin FTDI pui hexul cu bootloader integrat, daca nu te intereseaza asta il pui pe cel fara.

Link spre comentariu
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 spre comentariu

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 spre comentariu

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 spre comentariu
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 spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări