валкодер заменить кнопками
- Войдите на сайт для отправки комментариев
Доброго дня! Собрал радиоприемник по готовой схеме на ардуино нано с использованием олед дисплея и шилда с радиочипом 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);
}
Скетч прикрепил к первому посту, после фото.
Если с дребезгом не бороться и не оптимизировать, то, думаю, примерно так:
// 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; } }а вот получилось, все кнопки вывел, все круто! как ни странно, дребезг не повлиял, все сразу срабатывает. спасибо!