валкодер заменить кнопками

multimax
Offline
Зарегистрирован: 07.11.2017

Доброго дня! Собрал радиоприемник по готовой схеме на ардуино нано с использованием олед дисплея и шилда с радиочипом si4703. Изначально, автор этой сборки предусматривал использование валкодеров, дя изменения частоты приемника, а также громкости. Прошу помощи  в переделке управления с валкодеров на кнопки. На данный момент скетч думает что работает с валкодерами, опытным путем подсоединил кнопку к D2 и земле.. и оказалось, что она может менять частоту радиостанции вверх. По сути кнопкок нужны 4 штуки. Громкость +, громкость -, частота вверх, частота вниз. помогите пожалуйста хотя бы с одной кнопкой, для этого приемника, дальше я бы по аналогии попробовал сам. 

Проект, который я собирал: https://www.instructables.com/id/Si4703-FM-Radio-Arduino-Uno-Schield/

 

Прошу не относиться строго, я новичок, программистом не являюсь. Просто нравится паять и ковыряться в коде, попутно его изучая. В общих чертах за что отвечает каждый кусок в скетче - понимаю, могу читать. Но, увы язык знаю плохо. Тем не менее, безумно интересно учиться, попутно что-то собирая интересное. Буду рад помощи :) 

Скетч: 

/*  SI4703 fm radio with encoder switch 
 *   RDS RSSI 
 *   2017 03 20 
 */

#include <Si4703_Breakout.h>
#include <Wire.h>
#include <EEPROM.h>
#include "U8glib.h"  
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);
#define SI4703Address 0x10      // Si4703 I2C Address.

/*SI4703 - Pins*/
int resetPin = 6;
int SDIO = A4;
int SCLK = A5;
int RDSInterruptPin = 7; // GPIO2 for RDS Interrupt
unsigned int rdscount = 0;


/*EEPROM*/
int ChannelEEP=0x01;
int VolumeEEP=0x02;

/*GPO-ATMega*/
int StereoLED = 0x0D;
int AF_LED    = 0x05;
int RTReady =false;
int RDSReady=false;
int PSReady =false;


int channel_ant = 875;


// Setting up the channel
int lowest = 874;
int highest = 1081;
int changeamnt = 1;

// Setting up the volume
int low = 0;
int high = 30;
int changevol = 1;


// Timing for polling the encoder
unsigned long currentTime;
unsigned long lastTime;


// Pin definitions
const int pinA = 2;
const int pinB = 3;
const int pinC = 4;
const int pinD = 5;


// Storing the readings
boolean encA;
boolean encB;
boolean lastA = false;
boolean encC;
boolean encD;
boolean lastD = false;

/*Init SI4703 Driver*/
Si4703_Breakout radio(resetPin, SDIO, SCLK, RDSInterruptPin);

/*for SI4703*/
int channel;
int volume;

/*SI4703 RDS*/
char RT[65];
char PS[9];
char PTY[12];
char CLOCK[2];
char DATE[4];
int  AF[41];
char PICODE[2];
unsigned int PI_;

char TC[2];
int TC_;

const int VOID = 0;
const int EON  = 1;
const int TP   = 2;
const int TA   = 3;



void draw(void)
{
  int rssi=radio.getRSSI();



  
  u8g.setFont(u8g_font_profont15r);
    //u8g.drawStr(0, 12, " iriver ");
      u8g.setPrintPos(0, 12);

  PI_=((PICODE[1]&0xFF)+((PICODE[0]&0xFF)<<8));
  if(PI_)
  {
        
    u8g.println(PI_,HEX);
  }
  else
  {
 
    u8g.println("NoPI");
  
  }
  //меняем шрифт на более большой helvR14, для отображения частоты
   u8g.setFont(u8g_font_helvR14);
   
  u8g.setPrintPos(4, 34);
  u8g.println(channel/10.);

  
 //меняем шрифт на стандартный обратно для выполнения остальных кусков кода
  u8g.setFont(u8g_font_profont15r);
  
  u8g.setPrintPos(0, 64);
  u8g.println("RSSI ");
  u8g.println(rssi );
  u8g.println("dBm");

  u8g.setPrintPos(80, 64);
  u8g.println("VOL ");
  u8g.println(volume);



  
  u8g.drawRFrame(0, 15, 63, 25, 10);

  u8g.setPrintPos(70, 33);
  u8g.println(PS);


 //лулзовый шрифт микро, отлично подходит на мой взгляд для отображения формата станции
   u8g.setFont(u8g_font_micro);
u8g.setPrintPos(75, 20);
  u8g.println(PTY);

u8g.setPrintPos(02, 48);
  
 
        
  u8g.println("RT: ");
  u8g.println(RT);
  
  

  
}

void setup()
{
  // Init Pins
  //Output
  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);
  pinMode(pinC, INPUT_PULLUP);
  pinMode(pinD, INPUT_PULLUP);
  
  
   currentTime = millis();
   lastTime = currentTime; 
   pinMode(StereoLED, OUTPUT);
   digitalWrite(StereoLED, LOW);

  //Serial write Commands
  Serial.begin(9600);
  Serial.println("\n\nSi4703_Breakout Test Sketcfh");
  Serial.println("===========================");  
  Serial.println("a       Start AF seek");
  Serial.println("+ -     Volume (max 15)");
  Serial.println("u d     Auto seek up / down");
  Serial.println("w s     Manual seek up / down");
  Serial.println("r       Show RDS Data");
  Serial.println("Send me a command letter.");

  //Read last channel and volume
  GetDataFromEEP();

  //Initialize and Power up the SI4703
  radio.powerOn();
  radio.setVolume(volume);
  radio.setChannel(channel);
radio.setQuality(0); 
  //Print Informations to Serial Monitor
  displayInfo();
}

void loop()
{  
if (rdscount >= 10){
  
  RDSReady=radio.getRDS();
  if(RDSReady==true)
  {
    if(PSReady==false)
    {
      delay (50);
      char PS_[9];
      PSReady=radio.getPS(PS_);
      if(strlen(PS_)==8)strncpy(PS,PS_,8);
      Serial.println(PS);
      OledDisplayInfo();
//из-за этого мигало рдс!!!      SI4703_clearRDS();
      rdscount = 0;  
    }
    OledDisplayInfo();
    }
}
rdscount++;


 if (channel_ant != channel)
 {
      //SI4703_clearRDS();
      if(channel<875)channel=1080;
      if(channel>1080)channel=875;
      radio.setChannel(channel);
      SetDataToEEP();
      displayInfo();
      OledDisplayInfo();
      
      
      channel_ant = channel;
 }

 if (digitalRead(3) == LOW) 
 {

  // Read elapsed time
  currentTime = millis();
  // Check if it's time to read
  if(currentTime >= (lastTime ))
  {
    // read the two pins
    encC = digitalRead(pinC);
    encD = digitalRead(pinD);
    // check if C has gone from high to low
    if ((!encC) && (lastD))
    {
      // check if D is high
      if (encD)
      {
        // clockwise
        if (volume + changevol <= high)
        {
          volume = volume + changevol; 
        }
      }
      else
      {
        // anti-clockwise
        if (volume - changevol >= low)
        {
          volume = volume - changevol; 
        }
      }
      radio.setVolume(volume);
      OledDisplayInfo();
      displayInfo();
     
     
    }
    // store channel of A and millis for next loop
    lastD = encC;
    lastTime = currentTime;
  }
 }
  if (digitalRead(0) == CHANGE) 
{
 // Read elapsed time
  currentTime = millis();
  // Check if it's time to read
  if(currentTime >= (lastTime ))
  {
    // read the two pins
    encA = digitalRead(pinA);
    encB = digitalRead(pinB);
    // check if A has gone from high to low
    if ((!encA) && (lastA))
    {
      // check if B is high
      if (encB)
      {
        // clockwise
        if (channel + changeamnt <= highest)
        {
          channel = channel + changeamnt;         
        }
      }
      else
      {
        // anti-clockwise
        if (channel - changeamnt >= lowest)
        {
          channel = channel - changeamnt; 
        }
      }
     SI4703_clearRDS();
    }
    // store channel of A and millis for next loop
    lastA = encA;
    lastTime = currentTime;
  }
}
 SI4703_readRDS();

  //Serial Monitor input control
  if (Serial.available())
  {
    char ch = Serial.read();
    
    if (ch == 'u') 
    {
      Serial.println("\nAuto Search Up");
      SI4703_seekUpAuto();
    } 
    else if (ch == 'd') 
    {
      Serial.println("\nAuto Search Down");
      SI4703_seekDnAuto();
    } 
    else if (ch == '+') 
    {
      volume ++;
      if (volume == 31) volume = 30;
      radio.setVolume(volume);
      SetDataToEEP();
      displayInfo();
    } 
    else if (ch == '-') 
    {
      volume --;
      if (volume < 0) volume = 0;
      radio.setVolume(volume);
      SetDataToEEP();
      displayInfo();
    } 
    else if (ch == 'a')
    {
      SI4703_seekAF();
    }
    else if (ch == 'r')
    {
      displayRDS();
    }
    else if(ch == 'w')
    {
     channel++;
     SI4703_clearRDS();
     if(channel>1080)channel=875;
     displayInfo();
     SetDataToEEP();
     radio.setChannel(channel);
    }
    else if(ch == 's')
    {
     channel--;
     SI4703_clearRDS();
     if(channel<875)channel=1080;
     displayInfo();
     SetDataToEEP();
     radio.setChannel(channel);
    }
  }
}

void SI4703_seekUpAuto (void)
{
      //channel = radio.seekUp();
      SI4703_clearRDS();
      channel+=1;
      radio.setVolume(0);
      radio.setChannel(channel);
      delay(100);
      for(int seekup=channel;; seekup++)
      {
         if(seekup>1080)seekup=875;
         Serial.print(seekup/10.);Serial.println(" MHz");
         radio.setChannel(seekup);
         delay(30);
         int SI4703AFC_Tune=radio.getTune();
         int SI4703RSSI_Tune=radio.getRSSI();
         delay((SI4703RSSI_Tune*4));
         if(((SI4703AFC_Tune==false)&&(SI4703RSSI_Tune>20)))
         {
            radio.setVolume(volume);
            channel=seekup;
            SetDataToEEP();
            displayInfo();
            break;
         }
      }
      SI4703_clearRDS();
}

void SI4703_seekDnAuto (void)
{
      //channel = radio.seekDown();
      SI4703_clearRDS();
      channel-=1;
      radio.setVolume(0);
      radio.setChannel(channel);
      delay(100);
      for(int seekdown=channel;; seekdown--)
      {         
         if(seekdown<=875)seekdown=1080;
         Serial.print(seekdown/10.);Serial.println(" MHz");
         radio.setChannel(seekdown);
         delay(30);
         int SI4703AFC_Tune=radio.getTune();
         int SI4703RSSI_Tune=radio.getRSSI();
         delay((SI4703RSSI_Tune*4));
         if(((SI4703AFC_Tune==false)&&(SI4703RSSI_Tune>20)))
         {
            radio.setVolume(volume);
            channel=seekdown;
            SetDataToEEP();
            displayInfo();
            break;
         }
      }
      SI4703_clearRDS();
}
void SI4703_seekAF (void)
{
  int newChannel[1];
  Serial.println("AF seek starts now...!");
  while(!(radio.TuneAF(AF,PICODE,channel,volume)));
  if(newChannel)channel=newChannel[0];
  SetDataToEEP();
  displayInfo();
}
void displayInfo (void)
{
   int rssi=radio.getRSSI();
   int tune=radio.getTune();
   int stereo=radio.getStereo();
   Serial.print("\n\nChannel: "); Serial.print(channel/10.);Serial.println(" MHz");
   Serial.print("Volume: "); Serial.println(volume);
   Serial.print("RSSI: ");Serial.print(rssi);Serial.println("dBuV");
   Serial.print("Tune: ");
   if(tune==0)Serial.println("AFC Tuned!!");
   if(tune==1)Serial.println("AFC Tuning...");
   Serial.print("Sound: ");
   if(stereo==1){Serial.println("Stereo");digitalWrite(StereoLED, HIGH);}
   if(stereo==0){Serial.println("Mono");digitalWrite(StereoLED, LOW);}
   
}
void displayRDS (void)
{
  Serial.println();
  if(digitalRead(RDSInterruptPin)==LOW)
  Serial.println("RDS available!");
  
  if(strlen(PS)>=8)
  {
    Serial.print("PS: ");
    Serial.println(PS);
    for(int  Clear=0; Clear<8; Clear++)
    PS[Clear]=0;
  }
  else
  Serial.println("--No ProgrammServiceMessage success--");
    
  Serial.print("PTY: ");
  Serial.println(PTY);


    Serial.print("RT: ");
  Serial.println(RT);
  
  PI_=((PICODE[1]&0xFF)+((PICODE[0]&0xFF)<<8));
  if(PI_)
  {
    Serial.print("PI: ");
    //Serial.print(PICODE[0]&0xFF,HEX);Serial.println(PICODE[1]&0xFF,HEX);
    Serial.println(PI_,HEX);
  }
  else
  {
    Serial.println("--No PI-Code success--");
  }
  
  switch(TC_)
  {
    case VOID:
    {
      Serial.print("No Traffic Control is present");
    }break;
    
    case EON:
    {
      Serial.print("Channel support EON!");
    }break;

    case TP:
    {
      Serial.print("Traffic Pilot is available TP");
    }break;

    case TA:
    {
      Serial.print("Current traffic announcement TA");
    }break;
  }
 
  Serial.println();
}
void SI4703_readRDS (void)
{
    int RDSReady=false;
    RDSReady=radio.getRDS();
    if(RDSReady==true)
    {
      TC_=radio.getTC();      
      radio.getPS(PS);
      radio.getRT(RT);
      radio.getPTY(PTY);
      radio.getPI(PICODE);
      //radio.getTimeDate(CLOCK,DATE);
      radio.getAF(AF);
          
    }
}

void SI4703_clearRDS (void)
{ 
  radio.clearRDS(PS, RT, PTY, PICODE, AF);
}

void SetDataToEEP (void)
{  EEPROM.write(ChannelEEP,channel-875);
  EEPROM.write(VolumeEEP,volume);

}

void GetDataFromEEP (void)
{
  channel=EEPROM.read(ChannelEEP)+875;
  volume=EEPROM.read(VolumeEEP);
}


void OledDisplayInfo()
 {
   u8g.firstPage();
  do
  {
    draw();
  }
  while ( u8g.nextPage() );
   delay(10);
 }

 

multimax
Offline
Зарегистрирован: 07.11.2017

Скетч прикрепил к первому посту, после фото.

sadman41
Offline
Зарегистрирован: 19.10.2016

Если с дребезгом не бороться и не оптимизировать, то, думаю, примерно так:

    // read the two pins
    // encC = digitalRead(pinC);
    // encD = digitalRead(pinD);
    buttonC = digitalRead(pinC);
    buttonD = digitalRead(pinD);

    if (LOW == buttonC) {
        if (volume + changevol <= high)
        {
          volume = volume + changevol; 
        }
      }
    if (LOW == buttonD) {
        if (volume - changevol >= low)
        {
          volume = volume - changevol; 
        }
      }

А вот это убрать:

 if (digitalRead(3) == LOW) 
 {

  // Read elapsed time
  currentTime = millis();
  // Check if it's time to read
  if(currentTime >= (lastTime ))
  {

...

    }
    // store channel of A and millis for next loop
    lastD = encC;
    lastTime = currentTime;
  }
 }

 

multimax
Offline
Зарегистрирован: 07.11.2017

а вот получилось, все кнопки вывел, все круто! как ни странно, дребезг не повлиял, все сразу срабатывает. спасибо!