Themabewertung:
  • 1 Bewertung(en) - 5 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Arduino-Radio mit Leuchtbandanzeige
#1
Vorbereitend für ein Radioprojekt stelle ich hier schon mal die Platine vor. Ein Arduino Nano steuert einen SI4703 Baustein. Die Abstimmung erfolgt über Rotary Encoder und die Frequenzanzeige über ein LED-Strip.

   

   

   

LED-Strip:
Diese LED-Streifen gibt es als gerade Stücke, als Kreis oder Teilkreis, oder als Band als Meterware. Man schneidet sich ein passendes Stück des Bandes einfach ab (wie hier im Beispiel). Jede LED-Einheit setzt sich zusammen aus einem Miniprozessor und mehrfarbigen LED's. Der Hammer aber ist das es nur eine einzige Steuerleitung gibt und damit auch nur ein Digitalpin des Arduino benötigt wird. Die Steuerleitung und die Betriebsspannung von 5V wird von einer LED-Einheit zur nächsten weitergereicht. Es existieren libraries für alle möglichen bunten Effekte. Ich benutze hier eine wheel Funktion und lösche alle LED bevor ich die nächste LED setze. Dadurch entsteht ein wandernder Punkt. Farbe und Helligkeit sind parametrisierbar. Die Grundlagen hab ich mir hier angeeignet.

Rotary Encoder:
Die Funktionsweise ist hier sehr gut beschrieben. Im Prinzip keine große Sache. Trotzdem hat es mich tagelang beschäftigt bis die Abstimmung sauber funktionierte. Der Grund ist das Kontaktprellen der Schaltkontakte. Die Effekte waren Sprünge bei der Frequenzeinstellung, willkürliches Ändern der Drehrichtung, Verschlucken von Impulsen. Etwas Erfolge hatte ich mit dem Abfragen der Kontakte per Interruptfunktion, wobei die ansteigende bzw. abfallende Flanke ausgewertet wird. Ein zusätzliche Verbesserung brachte eine Zeitverzögerung, die in der Interruptfunktion per millis() einbaut wird. Zufriedenstellend war es immer noch nicht, und ich wollte schon von dem Encoder weg. Dann fand ich einen Hinweis auf eine hardware-Entprellung mit einem einfachen RC-Glied. Das war dann der Durchbruch. Die millis() konnte ich wieder rausnehmen, die Interrupts mussten bleiben. Der Encoder arbeitet jetzt ganz präzise und die Abstimmung ist endlich brauchbar. In die Leitungen der 2 Encodersignale kommen 10K Widerstände und 100n gegen Masse. Bei einer Auflösung von 100kHz pro Raster und 20 Rasterungen pro Umdrehung muss man natürlich schon etwas kurbeln um den Bereich durchzustimmen. Deshalb benutze ich noch zusätzlich den switch des Encoders um festeingestellte Empfangsfrequenzen zu toogeln.

Dann gab es ein weiteres großes Problem. Nach kurzem intensiven Durchstimmen der Frequenz gab es auf einmal reproduzierbar einen Frequenzversatz, so das die eingestellte Frequenz nicht mehr zur Frequenz passte den der SI4703 Baustein ausgab. Möglicherweise änderte der Baustein das Regionalband. Das Problem verschwand erst als ich die library austauschte. Das Programm basierte bis dahin auf der <SparkFunSi4703.h> library, nun arbeitet es stabil mit der Hertel-library <si4703.h>.

Auf dem Video steckt der library-Fehler noch drin, deshalb musste ich zwischendurch den Prozessor resetten:

Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#2
der aktuelle Programmcode. Wie üblich ein Zusammensetzen von code-Schnitzeln für die eigenen Bedürfnisse. Quellangaben sind soweit wie möglich eingebaut.

Code:
//bis jetzt fehlerfreie Funktion!
//Hertel-Library si4703.h
//learning about NeoPixel:
//https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library
//
/// Wiring
/// ------
/// The SI4703 board has to be connected by using the following connections:
/// | Arduino UNO pin    | Radio chip signal  |
/// | -------------------| -------------------|
/// | 3.3V (red)         | VCC                |
/// | GND (black)        | GND                |
/// | A5 or SCL (yellow) | SCLK               |
/// | A4 or SDA (blue)   | SDIO               |
/// | D2 (white)         | RST                |

//http://www.bristolwatch.com/arduino/arduino2.htm

#include <Arduino.h>
#include <Wire.h>
#include <radio.h>
#include <si4703.h>

#include <Adafruit_NeoPixel.h>
#define Din 4
int anz_led = 26; // Anzahl der LED's
Adafruit_NeoPixel strip = Adafruit_NeoPixel(anz_led, Din, NEO_GRB + NEO_KHZ800);
int wc = 0;
int led = 0;

// Input buttons on radio
#define preset 8
#define volDown 9            
#define volUp 10

//Rotary Encoder http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/keyes-ky-040-arduino-rotary-encoder-user-manual/
int clk = 3;  // Connected to CLK on KY-040
int dt = 7;  // Connected to DT on KY-040

// Si4703 radio chip
#define FIX_BAND     RADIO_BAND_FM   ///< The band that will be tuned by this sketch is FM.
SI4703 radio;    // Create an instance of Class for Si4703 Chip

// Variables definition
volatile int channel = 8800; // universal count
volatile byte INTFLAG1 = 0; // interrupt status flag
int volume = 10;

void setup()
{
  // Set internal pull up resistors on inputs
  pinMode(preset, INPUT_PULLUP);
  pinMode(volDown, INPUT_PULLUP);        
  pinMode(volUp, INPUT_PULLUP);
  
  //Rotary Encoder KY-040 pull up's built in
  pinMode (clk, INPUT);
  pinMode (dt, INPUT);

  // interrupt 1 digital pin 3 positive edge trigger
  attachInterrupt(digitalPinToInterrupt(clk), flag, RISING);  
  
  Serial.begin(9600);
  Serial.println(channel);

  // Set all radio setting to the fixed values.
  radio.init();
  radio.setBandFrequency(FIX_BAND, channel);
  radio.setVolume(volume);
  radio.setMono(false);
  radio.setMute(false);
  Serial.println("fixed values");
  
  //Initialize LED-Stripes
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  strip.setBrightness(64); //range 0 (off) to 255 (max brightness)
  UpdateLed();
  Serial.println("LED-Stripes");
  
}

void loop()
{
      
  // Volume down
  if (digitalRead(volDown) == LOW)
   {
     if (volume > 0) volume--;
     radio.setVolume(volume);
     delay(100);
   }  
  
  // Volume up
  if (digitalRead(volUp) == LOW)
   {
     if (volume < 15) volume++;
     radio.setVolume(volume);
     delay(100);
   }

  //Rotary Encoder
  if (INTFLAG1)   {
       INTFLAG1 = 0; // clear flag
       Serial.println(channel);
       Serial.println("ISP ausgelöst");
       radio.setFrequency(channel);
       UpdateLed();
       delay(40);
  } // end if  
    
  // Preset-Stationen http://www.w3ii.com/de/arduino/arduino_switch_case_statement.html
  if (digitalRead(preset) == LOW)
  {
    switch (channel){
    case 8800: channel = 9550; break;
    case 9550: channel = 10090; break;
    case 10090: channel = 10170; break;
    case 10170: channel = 10370; break;
    case 10370: channel = 8800; break;
    default: channel = 8800;
    }
    Serial.print("Preset: ");
    Serial.println(channel);
    radio.setFrequency(channel);
    UpdateLed();
    delay(100);
  }
  delay(50);    
}//end loop

//ISR for Encoder: http://www.bristolwatch.com/arduino/arduino2.htm
void flag() {
  INTFLAG1 = 1;
  // add 1 to count for CW
  if (digitalRead(clk) && digitalRead(dt)) {
    channel+=10 ;
    if (channel > 10800) channel = 8700;
  }
  // subtract 1 from count for CCW
  if (digitalRead(clk) && !digitalRead(dt)) {
    channel-=10 ;
    if (channel < 8700) channel = 10800;
  }
}

void UpdateLed()
{
strip.setPixelColor(led, strip.Color( 0, 0, 0));
led = map(channel, 8700, 10800, 0, (anz_led - 1));
strip.setPixelColor(led, Wheel(wc));
strip.show();
delay(20);
}

uint32_t Wheel(byte WheelPos) {
  if (WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#3
Sehr kreativ; prima!
Grüße aus dem Odenwald,

Werner



Lesen gefährdet die Dummheit!
Zitieren
#4
Jupp, ist ja sehr interessant, adressierbare, also einzeln anzusprechende LEDs habe ich bis jetzt noch nicht gekannt. Damit ist dann auch das Philips Ambilight gefallen. (Ist es ja eh schon lange)
Schöne Lösung, würde mich mal interessieren, wie es dann in einem schönen Gehäuse aussieht, welches man vom Schrott gerettet hat. Vielleicht sogar mit Rund- oder Halbrundskala.
Alte Geräte kurz vorm Schrott mit neuer Technik haben ihren Reiz. Ich mag das und könnte mir das gut vorstellen.
Viele Grüße 
Philipp
Zitieren
#5
Philipp, in genau solch eine Umgebung wird das Radiomodul eingebaut.

Die kleine hochkantstehende Platine ist ein NF-Verstärker mir LM386. Der genügt völlig um ein mittelgroßes Radio zu betreiben. Die Anordnung der Bauteile ist von der Platine weitgehend vorgegeben, da es sich um eine Steckbrett-Ersatz-Lochrasterplatine handelt. Das spart sehr viele Lötverbindungen.


.jpg   breadboard-platine.JPG (Größe: 31,07 KB / Downloads: 273)

Da der Arduino mit seinem internen Spannungsregler auch die LED-Kette versorgt habe ich einen 5V Nano Typ genommen. Das macht aber auch den Level-Converter für die 3,3V des SI4703-Modules notwendig.
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren


Möglicherweise verwandte Themen…
Thema Verfasser Antworten Ansichten Letzter Beitrag
Video Ilmenau_Teile, Teil 3. Ein UKW Ilmenau mit Arduino Nano navi 0 402 25.06.2023, 22:21
Letzter Beitrag: navi
  DDS AM Modulator mit Arduino Semir 74 42.167 20.01.2021, 16:18
Letzter Beitrag: Merlin_681
  SI4703 und Arduino Nano, zweite Generation mit RDS saarfranzose 5 6.148 01.04.2020, 19:37
Letzter Beitrag: navi
  AM-Modulator mit Arduino klammi † 1 2.542 29.03.2018, 20:49
Letzter Beitrag: Semir
  Stereo-Radiobasteln mit TEA5767 und Arduino Wilhelm † 2 4.829 29.10.2016, 07:42
Letzter Beitrag: Wilhelm †

Gehe zu: