Синтезатор (VFO) ad9850 и ILI9341 2.2
- Войдите на сайт для отправки комментариев
Втр, 02/08/2016 - 20:12
Здравствуйте.Появилась потребность в синтезаторе для трансивера.Взял готовый пример http://www.ad7c.com/projects/ad9850-dds-vfo/ и решил адаптировать его под цветной tft дисплей.Возникла трудность,при вращении н-кодера цифры на дисплее не обнавляются,а как бы пишутся поверх старых,т е был 0 а сверху написаллас 1 2 3 4 и в итоге каша. Подскажите что нужно добавить в коде?Может нужно сбрасывать постоянно при обновлении переменной,но как?
#include <rotary.h> #include <EEPROM.h> //Setup some items #define W_CLK 4 // Pin 8 - connect to AD9850 module word load clock pin (CLK) #define FQ_UD 5 // Pin 9 - connect to freq update pin (FQ) #define DATA 6 // Pin 10 - connect to serial data load pin (DATA) #define RESET 7 // Pin 11 - connect to reset pin (RST) #define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); } Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses. Must be interrupt pins. int_fast32_t rx=7200000; // Starting frequency of VFO int_fast32_t rx2=1; // variable to hold the updated frequency int_fast32_t increment = 10; // starting VFO update increment in HZ. int buttonstate = 0; String hertz = "10 Hz"; int hertzPosition = 5; byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; //Placeholders String freq; // string to hold the frequency int_fast32_t timepassed = millis(); // int to hold the arduino miilis since startup int memstatus = 1; // value to notify if memory is current or old. 0=old, 1=current. int ForceFreq = 1; // Change this to 0 after you upload and run a working sketch to activate the EEPROM memory. YOU MUST PUT THIS BACK TO 0 AND UPLOAD THE SKETCH AGAIN AFTER STARTING FREQUENCY IS SET! #include "SPI.h" #include "Adafruit_GFX.h" #include "Adafruit_ILI9341.h" #define TFT_DC 9 #define TFT_CS 10 #define TFT_MOSI 11 #define TFT_CLK 13 #define TFT_RST 8 #define TFT_MISO 12 Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO); void setup() { tft.begin(); tft.setRotation(1); tft.fillScreen(ILI9341_BLACK); pinMode(A0,INPUT); // Connect to a button that goes to GND on push digitalWrite(A0,HIGH); PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); pinMode(FQ_UD, OUTPUT); pinMode(W_CLK, OUTPUT); pinMode(DATA, OUTPUT); pinMode(RESET, OUTPUT); pulseHigh(RESET); pulseHigh(W_CLK); pulseHigh(FQ_UD); // this pulse enables serial mode on the AD9850 - Datasheet page 12. // Load the stored frequency if (ForceFreq == 0) { freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6)); rx = freq.toInt(); } } void loop() { if (rx != rx2){ showFreq(); sendFrequency(rx); rx2 = rx; } buttonstate = digitalRead(A0); if(buttonstate == LOW) { setincrement(); }; // Write the frequency to memory if not stored and 2 seconds have passed since the last frequency change. if(memstatus == 0){ if(timepassed+2000 < millis()){ storeMEM(); } } } ISR(PCINT2_vect) { unsigned char result = r.process(); if (result) { if (result == DIR_CW){rx=rx+increment;} else {rx=rx-increment;}; if (rx >=30000000){rx=rx2;}; // UPPER VFO LIMIT if (rx <=1000000){rx=rx2;}; // LOWER VFO LIMIT } } // frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32 void sendFrequency(double frequency) { int32_t freq = frequency * 4294967295/125000000; // note 125 MHz clock on 9850. You can make 'slight' tuning variations here by adjusting the clock frequency. for (int b=0; b<4; b++, freq>>=8) { tfr_byte(freq & 0xFF); } tfr_byte(0x000); // Final control byte, all 0 for 9850 chip pulseHigh(FQ_UD); // Done! Should see output } // transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line void tfr_byte(byte data) { for (int i=0; i<8; i++, data>>=1) { digitalWrite(DATA, data & 0x01); pulseHigh(W_CLK); //after each bit sent, CLK is pulsed high } } void setincrement(){ if(increment == 10){increment = 50; hertz = "50 Hz"; hertzPosition=5;} else if (increment == 50){increment = 100; hertz = "100 Hz"; hertzPosition=4;} else if (increment == 100){increment = 500; hertz="500 Hz"; hertzPosition=4;} else if (increment == 500){increment = 1000; hertz="1 Khz"; hertzPosition=6;} else if (increment == 1000){increment = 2500; hertz="2.5 Khz"; hertzPosition=4;} else if (increment == 2500){increment = 5000; hertz="5 Khz"; hertzPosition=6;} else if (increment == 5000){increment = 10000; hertz="10 Khz"; hertzPosition=5;} else if (increment == 10000){increment = 100000; hertz="100 Khz"; hertzPosition=4;} else if (increment == 100000){increment = 1000000; hertz="1 Mhz"; hertzPosition=6;} else{increment = 10; hertz = "10 Hz"; hertzPosition=5;}; //lcd.setCursor(0,1); **************************************************************************************************************************** //lcd.print(" "); //lcd.setCursor(hertzPosition,1); //lcd.print(hertz); tft.setTextColor(ILI9341_GREEN); tft.setTextSize(3); tft.setCursor(0,1); tft.print(" "); tft.setCursor(hertzPosition,1); tft.print(hertz); delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed. }; void showFreq(){ millions = int(rx/1000000); hundredthousands = ((rx/100000)%10); tenthousands = ((rx/10000)%10); thousands = ((rx/1000)%10); hundreds = ((rx/100)%10); tens = ((rx/10)%10); ones = ((rx/1)%10); // lcd.setCursor(0,0);******************************************************************************************************************************* // lcd.print(" "); tft.setTextColor(ILI9341_GREEN); tft.setTextSize(3); if (millions > 9){tft.setCursor(0, 0);} else{tft.setCursor(0, 6);} tft.print(millions); tft.print("."); tft.print(hundredthousands); tft.print(tenthousands); tft.print(thousands); tft.print("."); tft.print(hundreds); tft.print(tens); tft.print(ones); tft.print(" Mhz "); timepassed = millis(); memstatus = 0; // Trigger memory write }; void storeMEM(){ //Write each frequency section to a EPROM slot. Yes, it's cheating but it works! EEPROM.write(0,millions); EEPROM.write(1,hundredthousands); EEPROM.write(2,tenthousands); EEPROM.write(3,thousands); EEPROM.write(4,hundreds); EEPROM.write(5,tens); EEPROM.write(6,ones); memstatus = 1; // Let program know memory has been written };
Закрасьте чёрным квадратиком поле вывода цифр, перед тем как печатать. Можно и весь экран закрасить, по усмотрению.
Здравствуйте!Спасибо.Я Использовал следующие строчки в начале print на дисплей
Но,обновляется очень медленно,я поворачиваю н-кодер и и после этого,где то секунду обновляется квадратик,сверху вниз закрашивается черным.Что еще можно предпринять?Пологаю если закрашивать весь экран,то будет еще медленее.Нет каких то более быстрых "очисток" дисплея?
Ну, библиотека у Вас под руками, кому, как не Вам, смотреть, какие там есть функции.
Судя вот по этому:
интерфейс последовательный, протокол софтверный. Давайте посчитаем:
Вы выводите 200*40=8000 пикселей по два байта каждый. Это примерно 128 кбит. Если все это укладывается в секунду, то для указанных ограничений совсем не плохо.
Если аппаратной очистки нет, а скорость обновлекния экрана категорически не устраивает, существуют варианты:
1. Заменить диспдлей на другой - с параллельным интерфейсом. Минус - он займет минмум вдвое больше ног контроллера.
2. Отказаться от цветного дисплея в пользу монохромного (с однибитным цветом).
Я видел несколько видео на ютубе,к сожалению без кода,в которых обновление происходит в разы быстрее,вот например https://www.youtube.com/watch?v=rYAn4rj_MSk у меня по сравнению раз в шесть медленнее,не пойму в чем причина
varvik85, по вашей ссылке есть код: https://kennethwong.org/projects/electricaudi/instrument-cluster-part-2/
смотреть и комментировать лень :-)
У него библиотека другая, что вас останавливает содрать его код и посмотреть?
https://drive.google.com/file/d/0ByVBIKRZJdkIc2JoVzRjZ01kQkU/edit
Здравствуйте!Спасибо за помощь и интерес к моей проблеме.Дело в том,что мой дисплей не работает с другими библиотеками кроме Adafruit_ILI9341 пробовал разные TFT TFT2 UTFT UTFT-master с разными вариантами подключений,есть много примеров использования ILI9341 например http://arduino.ru/forum/apparatnye-voprosy/displei-na-ili9341 перепробовал все,не работает,работает только Adafruit_ILI9341 и инициализацией которая у меня в коде.То-же странно почему так,может я где-то косячу,но вроде неоднократно все перепроверял.Так вот, некоторые функции из библиотек TFT TFT2 UTFT UTFT не подходят для Adafruit_ILI9341 например initlcd() clrscr(); по этому не всегда получается использовать чужой код. Что работает так это tft.begin(); - инициализация дисплея и tft.fillRect(0, 0, 200, 40, ILI9341_BLACK); - тут я закрашиваю квадрат с цифрами черным,но закрашивается ооочень медлено,можно как то корректнее все это сделать,например не закрашивать квадрат а именно как то сбрасывать дисплей чтоб цифры менялись,но я не знаю какой командой.Может библиотека Adafruit_ILI9341 какая то корявая и по этому у меня так медленно все обновляется,или что то в коде что то тормозит?В любом случае,большое спасибо за советы!
У меня есть смутное подозрение, что скорость будет зависеть от способа инициализации адафрута-либа, там определено 2 конструктора.
Так вот, по второму способу, как и у вас, пины - произвольно выбираются, а значит используется бит-бэнг а не хардваре SPI. Попробуйте другую версию, короткую.
Здравствуйте.Спасибо.Но у меня опять ничего не работает.
подключаю дисплей к пинам (как в readme)
D4 : RESET
D5 : CS
D6 : D/C
D7 : LED
D11 : MOSI
D12 : MISO
D13 : SCK
Не работает
После меняю
DC на 9
CS на 10
Все равно не работает (((
Работает только та инициализация которая у меня в коде,почему?Что я не так подключаю?
Какой у вас дисплей? Фото, линк на веб-страницу и т.д.
Wiring
Wiring up the display in SPI mode is much easier than 8-bit mode since there's way fewer wires. Start by connecting the power pins
That's it! You do not need to connect the RST or other pins for now.
https://learn.adafruit.com/adafruit-2-dot-8-color-tft-touchscreen-breakout-v2/downloads?view=all#wiring
https://learn.adafruit.com/adafruit-2-dot-8-color-tft-touchscreen-breakout-v2/downloads?view=all#wiring
Здравствуйте.Спасибо!Дисплей у меня вот такой http://ru.aliexpress.com/item/Smart-Electronics-2-2-Inch-240-320-Dots-SPI-TFT-LCD-Serial-Port-Module-Display-ILI9341/32597442041.html?spm=2114.13010608.0.129.ZVa7Ud
Я подключал по описанию как Вы прислали,тишина....а вот
"That's it! You do not need to connect the RST or other pins for now." интересно,ресет не нужен получается,а почему?
Понятно, китай, они что угодно могут написать в названии. Может оказаться и не ILI9341 а SPFD5408 или ещё какой. У адафрута вроде должна писать тип контроллера при старте, у вас когда он работает там чего писало?
Да вродь ничего не писала,это измененная либа
Там ещё бенчмарк есть, не сравивали?
https://learn.adafruit.com/assets/15445
Понятно, китай, они что угодно могут написать в названии. Может оказаться и не ILI9341 а SPFD5408 или ещё какой. У адафрута вроде должна писать тип контроллера при старте, у вас когда он работает там чего писало?
Конкретно 9341 не имеет кода опознавания по стандартной процедуре. Если с какой то библиотекой инициализировался - это лучшее доказательство марки дисплея.
Если библиотека смогла нарисовать квадрат на экране, то этого достаточно, для реализации любых других действий. Если библиотека не может что то после этого сделать - это только вопрос кривых ручек. Чужой код легко подпрограммами-обёртками подгоняется к конкретной библиотеке,но это тоже влияет на скорость отрисовки.
Аппаратной очистки нет. Поэтому только программно чистить минимально необходимые квадраты. Скорость по SPI действительно очень маленькая. Только тотальная оптимизация кода и библиотеки даёт приемлемый результат. У меня ili9341 при 16 битной параллельной шине, при аппаратном заполнении через DMA, при тактовой частоте 72МГц заполняет весь экран 0.1 секунды. Множте эту цифру на spi(как минимум 16!) и на разницу в такте - получаются секунды в лучшем случае.
...0.1 секунды. Множте эту цифру на spi(как минимум 16!) и на разницу в такте - получаются секунды в лучшем случае.
16! = 20922789888000
Так что если верить Вам, то речь может идти не о секундах, а о сотнях тысяч лет.
Восклицательный знак прошу рассматривать как выражение экспрессии сообщения, а не как знак факториала :-)
А нокиа 5110 никто не привинчивал?