OLED дисплей 128*64 (вроде как ssd1306) показывает текст и фигуры через строку (т.е. одну строку закрашивает, следующую нет, после нее закрашивает и так далее.)

@Doloto , ты только не пропадай - Напиши помогло али нет? ))

Теперь вы “за ним еще три дня бегать будете … что бы фотграфию отдать …”

2 лайка

[quote=“BOOM, post:41, topic:13461”]
помогло али нет? ))
[/quote]
Помогло. Первый вариант внесенных изменений, дал положительный результат. Изображение на дисплее OLED SSD1306 0.96" I2C, развернулось на 180 градусов.

Второй вариант, без изменений.


Таким образом, можно констатировать факт, что решение проблемы, разворота изображения на дисплее OLED SSD1306 0.96" I2C, на 180 градусов, в скетче, возможно. Вопрос, совместными усилиями, решен. Всем объявляется благодарность. :+1: :man_student:

Что ты там такое конструируешь? Ну то есть где данный синтезатор будет применяться?

Это радиолюбительская конструкция, для синтезирования ВЧ сигналов, в полосе частот от 5КГц, до 225Мгц. Такой генератор можно использовать в радиоприемных и радиопередающих устройствах, а так же при налаживании различной радиотехники. Это очень удобно. Получается не дорогое, компактное (возможно с автономным питанием, от Li-ion элемента, напряжением 3.7-4.2 Вольта), практичное устройство, вполне годное для бытового применения. В общем удобно и доступно.

Я тебя не про Si5351 спрашивал, я и так знаю что это, а о том - что конструируешь?
Трансивер / приемник / etc ?

Etc собрал, для проверки радиоприемников. Кстати. Воодушевленным положительным результатом с работой OLED SSD1306, быстренько нашел ещё один проект, с более информативным отображением информации, с использованием Si5351a. Скетч был скомпилирован и загружен. Как и следовало ожидать, изображение на дисплее перевернутое.


Проблему перевернутого изображения решил тем же образом. Сработало.

Всю конструкцию разместил в “мыльнице”, для мыла. Получилось компактная конструкция. К выходу Si5351a, подключил отрезок медного провода. Разъем, пока выводить не стал. Питается вся конструкция от литиевого аккумулятора 18650, через плату заряда и защиты, на микросхеме ТР4056. Устройство получилось “бесконтактным”. Поднёс “мыльницу” к радиоприёмному устройству и можно с ним работать. В последствии установлю необходимые разъемы. Не знаю, на сколько Si5351a, боится статики по выходам. Есть неутешительная статистика. В общем, пока удобно именно так. Вот и само устройство.

Разъем по стандартную зарядку “micro USB”.

В общем как то так пока.

Главное, что решена проблема разворота изображения дисплея, на 180 градусов, из-за его не симметричности.

1 лайк

Поставь по выходам эмиттерные повторители, хуже точно не будет…

ЗЫ: В #47 строки 93 и 94 лишние, удали их вообще…

Да, скорее всего так и сделаю, да и это логично. На транзисторе или на низковольтной, скоростной микросхеме.

Здравия всем!
Смогут ли уважаемые Гуру, решить пару вопросов. Собрал синтезатор частот, на Si5351a. Вот код программы.

/**********************************************************************************************************

  10kHz to 225MHz VFO / RF Generator with Si5351 and Arduino Nano, with Intermediate
  Frequency (IF) offset
  (+ or -), RX/TX Selector for QRP Transceivers, Band Presets
  and Bargraph S-Meter. See the schematics for
  wiring and README.txt for details.
  By J. CesarSound - ver 2.0 - Feb/2021.
***********************************************************************************************************/

//Libraries
#include <Wire.h>                 //IDE Standard
#include <Rotary.h>               //Ben  Buxton https://github.com/brianlow/Rotary
#include <si5351.h>               //Etherkit  https://github.com/etherkit/Si5351Arduino
#include <Adafruit_GFX.h>         //Adafruit  GFX https://github.com/adafruit/Adafruit-GFX-Library
#include <Adafruit_SSD1306.h>     //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306

//User   preferences
//------------------------------------------------------------------------------------------------------------
#define IF  0                // 455    //Enter your IF frequency, ex: 455 = 455kHz, 10700 = 10.7MHz,
                             //0 = to direct convert receiver or RF generator, + will add and - will subtract IF   //offfset.
#define BAND_INIT  7         //Enter your initial Band (1-21) at startup, 
                             //ex: 1 = Freq Generator, 2 = 800kHz (MW), 7 = 7.2MHz (40m), 11 = 14.1MHz (20m). 
#define XT_CAL_F   33000     //Si5351 calibration factor, adjust to get exatcly 10MHz. Increasing  this value will decreases the frequency and vice versa.
#define S_GAIN     404       //Adjust the sensitivity of Signal Meter A/D input: 101 = 500mv; 202 = 1v;  303 = 1.5v; 404 = 2v; 505 = 2.5v; 1010 = 5v (max).
#define tunestep   A0        //The  pin used by tune step push button.
#define band       A1        //The pin used  //by band selector push button.
#define rx_tx      A2        //The pin used by  RX / TX selector switch, RX = switch open, TX = switch closed to GND. When in TX, the IF value is not considered.
#define adc        A3        //The pin used by  Signal Meter A/D input.
//------------------------------------------------------------------------------------------------------------

Rotary r = Rotary(2, 3);
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
Si5351 si5351(0x60);         //Si5351 I2C Address 0x60

unsigned long freq, freqold, fstep;
long interfreq = IF, interfreqold = 0;
long cal = XT_CAL_F;
unsigned int smval;
byte encoder = 1;
byte stp, n = 1;
byte count, x, xo;
bool sts = 0;
unsigned int period = 100;
unsigned long time_now = 0;

ISR(PCINT2_vect) {
  char
  result = r.process();
  if (result == DIR_CW) set_frequency(1);
  else if  (result == DIR_CCW) set_frequency(-1);
}

void set_frequency(short dir)
  {
  if (encoder == 1) {          //Up/Down frequency
    if (dir == 1) freq = freq + fstep;
    if (freq >= 225000000) freq = 225000000;
    if (dir == -1) freq = freq - fstep;
    if (fstep == 1000000 && freq <= 1000000) freq = 1000000;
    else if (freq < 5000) freq = 5000;
  }
  if (encoder == 1) {          //Up/Down graph tune pointer
    if (dir == 1) n = n + 1;
    if (n > 42) n = 1;
    if (dir == -1) n = n - 1;
    if (n < 1) n = 42;
  }
}

void setup() {
  Wire.begin();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.ssd1306_command(0xA0);
  display.ssd1306_command(0xC0);
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.display();

  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(tunestep, INPUT_PULLUP);
  pinMode(band, INPUT_PULLUP);
  pinMode(rx_tx, INPUT_PULLUP);


  //statup_text();  //If you hang on startup, comment

  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
  si5351.set_correction(cal, SI5351_PLL_INPUT_XO);
  si5351.drive_strength(SI5351_CLK0,  SI5351_DRIVE_8MA);
  si5351.output_enable(SI5351_CLK0, 1);   //1  - Enable / 0 - Disable CLK
  si5351.output_enable(SI5351_CLK1, 0);
  si5351.output_enable(SI5351_CLK2, 0);

  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);

  sei();

  count = BAND_INIT;
  bandpresets();
  stp = 4;
  setstep();
}

void
  loop() {
  if (freqold != freq) {
    time_now = millis();
    tunegen();
    freqold = freq;
  }

  if (interfreqold != interfreq) {
    time_now = millis();
    tunegen();
    interfreqold = interfreq;
  }

  if
  (xo != x) {
    time_now = millis();
    xo = x;
  }

  if (digitalRead(tunestep) == LOW) {
    time_now = (millis() + 300);
    setstep();
    delay(300);
  }

  if (digitalRead(band) == LOW) {
    time_now = (millis() + 300);
    inc_preset();
    delay(300);
  }

  if (digitalRead(rx_tx) == LOW)
  {
    time_now = (millis() + 300);
    sts = 1;
  } else sts = 0;


  if ((time_now + period) > millis()) {
    displayfreq();
    layout();
  }
  sgnalread();
}

void tunegen() {
  si5351.set_freq((freq +
  (interfreq * 1000ULL)) * 100ULL, SI5351_CLK0);
}

void displayfreq() {

  unsigned int m = freq / 1000000;
  unsigned int k = (freq % 1000000) / 1000;
  unsigned int h = (freq % 1000) / 1;

  display.clearDisplay();
  display.setTextSize(2);

  char buffer[15] = "";
  if (m < 1) {
    display.setCursor(41, 1); sprintf(buffer, "%003d.%003d", k, h);
  }
  else if (m < 100) {
   display.setCursor(5,  1); 
   sprintf(buffer, "%2d.%003d.%003d", m, k, h);
  }
  else if (m >= 100)
  {
    unsigned int h = (freq % 1000) / 10;
    display.setCursor(5, 1); sprintf(buffer,  "%2d.%003d.%02d", m, k, h);
  }
  display.print(buffer);
}

void
  setstep() {
  switch (stp) {
    case 1: stp = 2; fstep = 1; break;
    case 2: stp = 3; fstep = 10; break;
    case 3: stp = 4; fstep = 100; break;
    case 4: stp = 5; fstep = 1000; break;
    case 5: stp = 6; fstep = 5000;  break;
    case 6: stp = 7; fstep = 10000; break;
    case 7: stp = 8; fstep = 100000; break;
    case 8: stp = 1; fstep = 1000000; break;
    
  }
}

void inc_preset()
  {
  count++;
  if (count > 21) count = 1;
  bandpresets();
  delay(50);
}

void
  bandpresets() {
  switch (count)  {
    case  1: freq = 100000; tunegen();  break;
    case  2: freq = 800000; break;
    case  3: freq = 1800000; break;
    case  4: freq = 3650000; break;
    case  5: freq = 4985000; break;
    case  6: freq = 6180000; break;
    case  7: freq = 7200000; break;
    case  8: freq = 10000000; break;
    case  9: freq = 11780000; break;
    case 10: freq = 13630000; break;
    case 11: freq = 14100000; break;
    case 12: freq = 15000000; break;
    case 13: freq = 17655000; break;
    case 14: freq = 21525000; break;
    case 15: freq = 27015000; break;
    case 16: freq = 28400000; break;
    case 17: freq = 50000000; break;
    case 18: freq = 100000000; break;
    case 19: freq = 130000000; break;
    case 20: freq = 144000000; break;
    case 21: freq = 220000000; break;
  }
  si5351.pll_reset(SI5351_PLLA);
  stp = 4; setstep();
}

void layout() {
  display.setTextColor(WHITE);
  display.drawLine(0, 20, 127, 20, WHITE);
  display.drawLine(0, 43, 127, 43, WHITE);
  display.drawLine(105, 24, 105, 39, WHITE);
  display.drawLine(87,  24, 87, 39, WHITE);
  display.drawLine(87, 48, 87, 63, WHITE);
  display.drawLine(15, 55, 82, 55, WHITE);
  display.setTextSize(1);
  display.setCursor(59, 23);
  display.print("STEP");
  display.setCursor(50, 33);
  if (stp == 2) display.print("   1Hz"); 
  if (stp == 3) display.print("  10Hz"); 
  if (stp == 4) display.print(" 100Hz");
  if (stp == 5) display.print("  1kHz"); 
  if (stp == 6) display.print("  5kHz");
  if (stp == 7) display.print(" 10kHz");
  if (stp == 8) display.print("100kHz");
  if (stp == 1) display.print("  1MHz"); 
  
  display.setTextSize(1);
  display.setCursor(92, 48);
  display.print("IF:");
  display.setCursor(92, 57);
  display.print(interfreq);

  display.print("k");
  display.setTextSize(1);
  display.setCursor(110, 23);
  if (freq < 1000000) display.print("kHz");
  if (freq >= 1000000) display.print("MHz");
  display.setCursor(110, 33);
  if (interfreq == 0)
  display.print("VFO");
  if (interfreq != 0) display.print("L O");
  display.setCursor(91, 28);
  if (!sts) display.print("RX"); if (!sts) interfreq = IF;
  if (sts)  display.print("TX"); if (sts) interfreq = 0;
  bandlist(); drawbargraph();
  display.display();
}

void bandlist() {
  display.setTextSize(2);
  display.setCursor(0, 25);
  if (count == 1) display.print("GEN"); 
  if (count == 2) display.print("MW"); 
  if (count == 3) display.print("160m"); 
  if (count == 4) display.print("80m");
  if (count == 5) display.print("60m"); 
  if (count == 6) display.print("49m"); 
  if (count == 7) display.print("40m"); 
  if (count == 8) display.print("31m");
  if (count == 9) display.print("25m"); 
  if (count == 10) display.print("22m"); 
  if (count == 11) display.print("20m"); 
  if (count == 12) display.print("19m");
  if (count == 13) display.print("16m"); 
  if (count == 14) display.print("13m"); 
  if (count == 15) display.print("11m"); 
  if (count == 16) display.print("10m");
  if (count == 17) display.print("6m");
  if (count == 18) display.print("WFM"); 
  if (count == 19) display.print("AIR");
  if (count == 20) display.print("2m");
  if (count == 21) display.print("1m");
  if (count == 1) interfreq = 0; 
  else if (!sts) interfreq = IF;
}

void
  sgnalread() {
  smval = analogRead(adc); x = map(smval, 0, S_GAIN, 1, 14); if (x > 14) x = 14;
}

void drawbargraph() {
  byte y = map(n, 1, 42, 1, 14);
  display.setTextSize(1);

  //Pointer
  display.setCursor(0, 48);
  display.print("TU");
  switch (y) {
    case  1: display.fillRect(15, 48, 2, 6, WHITE); break;
    case  2: display.fillRect(20, 48, 2, 6, WHITE); break;
    case  3: display.fillRect(25, 48, 2, 6, WHITE); break;
    case  4: display.fillRect(30, 48, 2, 6, WHITE); break;
    case  5: display.fillRect(35, 48, 2, 6, WHITE); break;
    case  6: display.fillRect(40, 48, 2, 6, WHITE); break;
    case  7: display.fillRect(45, 48, 2, 6, WHITE); break;
    case  8: display.fillRect(50, 48, 2, 6, WHITE); break;
    case  9: display.fillRect(55, 48, 2, 6, WHITE); break;
    case 10: display.fillRect(60, 48, 2, 6, WHITE); break;
    case 11: display.fillRect(65, 48, 2, 6, WHITE); break;
    case 12: display.fillRect(70, 48, 2, 6, WHITE); break;
    case 13: display.fillRect(75, 48, 2, 6, WHITE); break;
    case 14: display.fillRect(80, 48, 2, 6, WHITE); break;
  }

  //Bargraph
  display.setCursor(0, 57);
  display.print("SM");
  switch (x) {
    case 14: display.fillRect(80, 58, 2, 6, WHITE);
    case 13: display.fillRect(75, 58, 2, 6, WHITE);
    case 12: display.fillRect(70, 58, 2, 6, WHITE);
    case 11: display.fillRect(65, 58, 2, 6, WHITE);
    case 10: display.fillRect(60, 58, 2, 6, WHITE);
    case  9: display.fillRect(55, 58, 2, 6, WHITE);
    case  8: display.fillRect(50, 58, 2, 6, WHITE);
    case  7: display.fillRect(45, 58, 2, 6, WHITE);
    case  6: display.fillRect(40, 58, 2, 6, WHITE);
    case  5: display.fillRect(35, 58, 2, 6, WHITE);
    case  4: display.fillRect(30, 58, 2, 6, WHITE);
    case  3: display.fillRect(25, 58, 2, 6, WHITE);
    case  2: display.fillRect(20, 58, 2, 6, WHITE);
    case  1: display.fillRect(15, 58, 2, 6, WHITE);
  }
}

void
  statup_text() {
  display.setTextSize(1); display.setCursor(13, 18);
  display.print("Si5351 VFO/RF GEN");
  display.setCursor(6, 40);
  display.print("JCR RADIO - Ver 2.0");
  display.display(); delay(2000);
}

Всё компилируется, загружается и работает, но, при эксплуатации, выявились два момента.
Первый. Это мало шагов сетки частот.

Можно ли увеличить количество шагов перестройки синтезатора, раза в два например? Если да, то как?
Второй момент. В конце кода, есть строки вывода на экран некой информации, при подачи питания на устройство.

Но при включении устройства, информация не выводится на экран, а сразу выводится рабочий экран синтезатора. Это конечно не критично, но возможна какая то ошибка, хотя при компиляции, отсутствует сообщение об ошибке. Почему? :thinking:

87-я строка

Хренасе… Простите мой французский…
От одного герца, до мегагерца. Куда больше то???

А так … Не вижу ничего сложного…

Но нахрена столько? Не пониманию… объяснишь?

Ну не может человек два-три раза щелкнуть кнопарь …

1 лайк

Ага. Понял. Сделал как рекомендовано. РазРемил указанную строку.


При компиляции выдает ошибку.

Так и будете кусками кода на фотках кидаться ? УСПЕХОВ !!!

Для комфортной работы, в пределах доступных диапазонов. Например. СВ диапазон (шаг 9 КГц), Авиа диапазон (шаг 8.33 КГц) и т.д., + это даёт возможность быстро перестраиваться, при необходимости, с минимальным количеством поворотов энкодера.
Я пробовал просто добавлять строки

[quote="Doloto, post:50, topic:13461"]

case 8: stp = 9; fstep = 1000000; break;
case 9: stp = 10; fstep = 10000000; break;
case 10: stp = 11; fstep = 30000000; break;
case 11: stp = 1; fstep = 100000000; break;

[/quote]
Результат отрицательный. Так в коде есть какая то привязка к строкам

display.setCursor(50, 33);
  if (stp == 2) display.print("   1Hz"); 
  if (stp == 3) display.print("  10Hz"); 
  if (stp == 4) display.print(" 100Hz");
  if (stp == 5) display.print("  1kHz"); 
  if (stp == 6) display.print("  5kHz");
  if (stp == 7) display.print(" 10kHz");
  if (stp == 8) display.print("100kHz");
  if (stp == 1) display.print("  1MHz"); 

Но как это связано не знаю.

Так вроде исходный код загрузил целиком, постами выше. Что не так? :thinking:

То и не так - если вам нужна помощь, зачем вы вынуждаете тех, кто пытается вам помочь, ломать глаза, разглядывая картинки? Вам так трудно скопипастить текстом?

То что проблема с переворотом изображения решилась - это хорошо. Но нафига с этим было заморачиваться в конкретно данном случае? Неужели получившееся устройство весит 50 кило и оно непереворачиваемое? Это же “мыльница”, крути верти её как хошь…