Простой AVR-управляемый FM-приемник
- Войдите на сайт для отправки комментариев
Добрый день. Наткнулся на проект простого управляемого ардуиной приемника. Проект по адресу https://alexkaltsas.wordprecc.com/2018/05/01/a-simple-avr-controlled-fm-receiver Там же есть ссылка на видеоролик в ютубе. Тюнер в приемнике использован фирменный собран на LC7213V с синтезатором частоты PLL c LA1837M. Я не являюсь специалистом по этим вопросам поэтому при попытке собрать это устройство возникли трудности, а именно:
1. Выложенный проект не дает понимания на какой платформе он разрабатывался . AVR Studio 7 обругала выдала кучу ошибок и не нашла ссылки на библиотеки проекта.
2. В файлах любезно представленных разработчиком я нашел HEX файлы. Но не понял какой из них является прошивкой для Ардуино.
3. Не ясно чем же шился Ардуино.
4. И не был ли при прошивке снесен родной загрузчик ардуино.
Буду признателен за Ваши коментарии и разьяснения по этому проекту.
С уважением !
[quote=metrologsastem12]
Исправлен адрес Проекта https://alexkaltsas.wordpress.com/2018/05/01/a-simple-avr-controlled-fm-receiver
У проекта есть автор. Тебе туда.
1. компилятор AVR-GCC
2. AVR_Radio.hex находится в AVR_Radio-master\Firmware\bin\Release
3. программатор USBASP интерфейс SPI или вы можете применить arduino в режиме SPI
4. загрузчик uart стирается (затирается)
софт компиляция хорошо, персонально проверка
Доброго дня Уважаемые участники форума!
Благодарю !
Низкий поклон "strarbit" за компетентный и быстрый ответ!
Без Вашей помощи реализация этот проекта была бы невозможна!!
Постараюсь в ближайшее время сообщить на этой ветке форума о результатах его реализации.
С уважением!
господин metrologsaste, эти слова нет нет ненужно никогда! Уважением!
Доброго дня участники форума! В реализацию проекта вклинился тайм-Аут, связанный с тем, что присланная посылка с заказом платформы Arduino UNO, на самом деле оказалась Arduino Duemilanove.
Сейчас нахожусь в легком охренении поскольку:
1. Идея состояла в том, чтобы из сокета платформы Arduino UNO, которую использовал автор проекта alexkaltsas , изьять оригинальную Atmega 238P-PU и поставить прошитую Atmega 238P-PU дампом AVR_Radio.hex , автора проекта с адреса https://github.com/firew4lker/AVR_Radio/blob/master/Firmware/bin/Release/AVR_Radio.hex.
2. Прошивку с дампом AVR_Radio.hex предполагалось вливать в чистую Atmega 238P-PU с помощью программатора MiniPro TL866A (штатным ПО программатора) и затем установить в посадочное место взамен оригинальной.
3. Учитывая различия платформ Arduino UNO и Arduino Duemilanove возникает опасение в самой возможности такой замены.
Я побаиваюсь, что таким образом можно вывести из строя Arduino Duemilanove. Заранее благодарен за Ваши советы и комментарии.
С уважением!
Какие различия в плптформах вы видите?
Увы, я не являюсь специалистом, и ориентируюсь по внешнему виду платы. (Что находится на борту каждой из них) О прошивках рассуждать я тоже не могу, - нет знаний. Кроме этого, к сожалению я не могу в своем комментарии представить их внешинй вид, поскольку не освоился с сервисами форума. В этом деле мой уровень начинающего любителя.
Но фото этих плат представлены на вкладке Сайта Контроллеры Ардуино.
С уважением!
Доброго дня участники форума! В реализацию проекта вклинился тайм-Аут, связанный с тем, что присланная посылка с заказом платформы Arduino UNO, на самом деле оказалась Arduino Duemilanove.
Сейчас нахожусь в легком охренении поскольку:
1. Идея состояла в том, чтобы из сокета платформы Arduino UNO, которую использовал автор проекта alexkaltsas , изьять оригинальную Atmega 238P-PU и поставить прошитую Atmega 238P-PU дампом AVR_Radio.hex , автора проекта с адреса https://github.com/firew4lker/AVR_Radio/blob/master/Firmware/bin/Release/AVR_Radio.hex.
2. Прошивку с дампом AVR_Radio.hex предполагалось вливать в чистую Atmega 238P-PU с помощью программатора MiniPro TL866A (штатным ПО программатора) и затем установить в посадочное место взамен оригинальной.
3. Учитывая различия платформ Arduino UNO и Arduino Duemilanove возникает опасение в самой возможности такой замены.
Я побаиваюсь, что таким образом можно вывести из строя Arduino Duemilanove. Заранее благодарен за Ваши советы и комментарии.
С уважением!
Увы, я не являюсь специалистом, и ориентируюсь по внешнему виду платы. (Что находится на борту каждой из них) О прошивках рассуждать я тоже не могу, - нет знаний.
Я из своего Duemilanove вытащил ATMega168 и засунул ATMega328 с алиэкспресса, предварительно залив бутлоадер. Она уже года четыре работает и не чихает. Так что ничего страшного произойти от вашей замены не должно.
Благодарю за совет sadman41!
Однако, в сути своей задача обратная той, - о которой говорите Вы! Постараюсь подробней пояснить это:
1. Есть проект собраный на плате Arduino UNO, с примочками на борту и своим ПО (бутлодер,+ фьюзы). Шился проект как сказано выше более компетентным участником форума на платформе Arduino UNO . При этом бутлодер затираеться, что с фьюзами, - одному богу известно, поскольку в представленной информации по проекту об этом ни гу-гу. Ссылки на проект выше.
2. У меня плата другая, а именно, - Arduino Duemilanove, с другими примочками на борту и т.д.
Вот из-за этого и возник вопрос о взаимозаменяемости. И звучит он другими словами так:
Можно ли использовать Arduino Duemilanove в этом проекте вместо Arduino UNO?
Естественно, не повредив плату Arduino Duemianove.
С уважением!
Так я и пишу, что явных проблем не вижу. МК один и тот же. Duemilanove - это предок Uno. Различия между ними в USB-UART мосте, но он наврядли будет препятствовать нормальной работе, так как является самостоятельной частью схемы и соединен с МК однотипно в обоих случаях - к RX/TX (D0/D1).
Благодарю за уточнение! Попробую воспользоваться Вашим советом.
Еще один вопрос связанный с реализацией проекта:
Поскольку оригинал буду извлекать и на его место ставить прошитую дампом проекта ( Atmega 328P-PU) то наверное при прошивке все настройки регистров нужно устанавливать как в исходнике, - Arduino UNO или это не принципиально?
С уважением!
Покак кто-то из нас этого не попробует сделать - ответа получить не выйдет. Сжечь МК вы наврядли сумеете.
Благодарю!
Пойду пробовать. Страшно!!! Отпишусь о результатах на ветке.
С уважением!
делал приемник на синтезаторе LC72131, управлял Pro Mini ATmega328P 5V / 16MHz - аналог UNO
http://arduino.ru/forum/apparatnye-voprosy/muzykalnyi-tsentr-lg-cd-962-c...
В теме есть ссылки на используемые библиотеки.
нарыл у себя скетч чисто для приемника.
/* The module is based on a Sanyo LC72131 PLL and a tuner IC. The PLL can communicate with a microcontroller via the Sanyo CCB bus, and have 5 I/O pins which controls the tuner: PLL pin Direction Function BO0 PLL -> Tuner Not used BO1 PLL -> Tuner Band selector (0 = FM; 1 = AM) BO2 PLL -> Tuner Mute / IF output (0 = Mute / IF counter mode 1 = Normal tuner mode) BO3 PLL -> Tuner Audio mode (0 = Stereo; 1 = Mono) BO4 PLL -> Tuner Not used IO0 Tuner -> PLL Not used (pulled high. Reads "1") IO1 Tuner -> PLL Stereo indicator (0 = Stereo; 1 = Mono) Note: BO0 must be set to "0" for the tuner to output the IF signal to the PLL. This means the tuner will have to be muted every time one want the PLL to count the IF frequency. Note: This example uses an analog keypad with the following schematics: A0 | 2k2 | 330R 620R 1k 3k3 VCC -----\/\/\---+---\/\/\---+---\/\/\---+---\/\/\---+---\/\/\-----+----- GND | | | | | X SCAN_UP X UP X DOWN X SCAN_DOWN X BAND | | | | | GND GND GND GND GND X = keys (N.O.) */ #include <inttypes.h> #include <LiquidCrystal.h> #include <SanyoCCB.h> // This example uses an analog 5-key keypad tied to A0 #define KEYPAD_PIN A0 // Keypad keys #define KEY_BAND 5 #define KEY_SCAN_DOWN 4 #define KEY_DOWN 3 #define KEY_UP 2 #define KEY_SCAN_UP 1 #define KEY_NONE 0 // LC72131 IN1, byte 0 #define IN10_R3 7 #define IN10_R2 6 #define IN10_R1 5 #define IN10_R0 4 #define IN10_XS 3 #define IN10_CTE 2 #define IN10_DVS 1 #define IN10_SNS 0 // LC72131 IN2, byte 0 #define IN20_TEST2 7 #define IN20_TEST1 6 #define IN20_TEST0 5 #define IN20_IFS 4 #define IN20_DLC 3 #define IN20_TBC 2 #define IN20_GT1 1 #define IN20_GT0 0 // LC72131 IN2, byte 1 #define IN21_DZ1 7 #define IN21_DZ0 6 #define IN21_UL1 5 #define IN21_UL0 4 #define IN21_DOC2 3 #define IN21_DOC1 2 #define IN21_DOC0 1 #define IN21_DNC 0 // LC72131 IN2, byte 2 #define IN22_BO4 7 #define IN22_BO3 6 #define IN22_BO2 5 #define IN22_BO1 4 #define IN22_IO2 3 #define IN22_IO1 2 #define IN22_IOC2 1 #define IN22_IOC1 0 // LC72131 DO0, byte 0 #define DO0_IN2 7 #define DO0_IN1 6 #define DO0_UL 4 // For function YST93xSetMode #define YST93x_MONO 1 #define YST93x_STEREO 2 #define YST93x_MUTE 3 #define YST93x_UNMUTE 4 #define YST93x_BAND_FM 5 #define YST93x_BAND_AM 6 // Acceptable IF frequency deviation window (for the PLL) when searching for radio stations // You may need to tweek these values to have a reliable "scan" mode #define FM_TUNED_WINDOW 180 #define AM_TUNED_WINDOW 20 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // назначение пинов для дисплея // RS E D4 D5 D6 D7 SanyoCCB ccb(12, 13, 11, 10); // назначение пинов для синтезатора // Pins: DI> CL DO< CE byte pll_in1[3]; // глобальная переменная 3x8 бит или 3 байта byte pll_in2[3]; // Initial frequencies uint16_t FMFrequency = 1044; // MHz / 10 начальная частота FM uint16_t AMFrequency = 53; // KHZ * 10 uint8_t band = YST93x_BAND_FM; uint8_t tuned = 0; /************************************************\ * YST93xInit() * * Initialize the PLL settings vectors with * * parameters common to booth AM and FM modes * \************************************************/ void YST93xInit() { memset(pll_in1, 0, 3); // 1 - Указатель на блок памяти для заполнения. // 2 - Установка значения. Передается как int // без знака этого значения. // 3 - количество байт, которое должно быть установлено. memset(pll_in2, 0, 3); bitSet(pll_in2[0], IN20_IFS); // IF counter in normal mode bitSet(pll_in2[1], IN21_UL0); // Phase error detection width = 0us bitSet(pll_in2[2], IN22_BO2); // Mute off / normal tuner mode //bitSet(pll_in1[0], IN10_XS); // Кварц 7.2 МГц СМ. НИЖЕ ....! bitClear(pll_in1[0], IN10_XS); // Кварц 4.5 МГц } /************************************************\ * YST93xSetMode() * * Some predefined setups for the YST93x module * \************************************************/ void YST93xSetMode(uint8_t mode) { switch(mode) { case YST93x_STEREO: bitClear(pll_in2[2], IN22_BO3); break; case YST93x_MONO: bitSet(pll_in2[2], IN22_BO3); break; case YST93x_MUTE: bitClear(pll_in2[2], IN22_BO2); break; case YST93x_UNMUTE: bitSet(pll_in2[2], IN22_BO2); break; case YST93x_BAND_FM: band = YST93x_BAND_FM; bitWrite(pll_in1[0], IN10_R0, 1); // Reference frequency = 50kHz / 10 кГц R0->0 bitWrite(pll_in1[0], IN10_R3, 0); // R3->1 bitWrite(pll_in1[0], IN10_DVS, 1); // Programmable Divider divisor = 2 bitWrite(pll_in2[0], IN20_GT0, 0); // IF counter mesurement period = 32ms bitWrite(pll_in2[0], IN20_GT1, 1); // bitWrite(pll_in2[1], IN21_DZ0, 1); // Dead zone = DZB bitWrite(pll_in2[1], IN21_DZ1, 0); // bitWrite(pll_in2[2], IN22_BO1, 0); // FM mode break; case YST93x_BAND_AM: band = YST93x_BAND_AM; bitWrite(pll_in1[0], IN10_R0, 0); // Reference frequency = 10kHz bitWrite(pll_in1[0], IN10_R3, 1); // bitWrite(pll_in1[0], IN10_DVS, 0); // Programmable Divider divisor = 1 bitWrite(pll_in2[0], IN20_GT0, 1); // IF counter mesurement period = 8ms bitWrite(pll_in2[0], IN20_GT1, 0); // bitWrite(pll_in2[1], IN21_DZ0, 0); // Dead zone = DZC bitWrite(pll_in2[1], IN21_DZ1, 1); // bitWrite(pll_in2[2], IN22_BO1, 1); // AM mode break; } ccb.write(0x82, pll_in1, 3); ccb.write(0x92, pll_in2, 3); } /************************************************************\ * YST93xTune() * * Set the tuner frequency and return 1 if it is tuned * * or 0 otherwise. * * * * The frequency divisors was chosen in a way the frequency * * representation can be directly sent to the PLL and is * * easy to represent: * * - FM mode (divisor = 100): frequency (MHz) * 10 * * - AM mode (divisor = 10): frequency (kHZ) / 10 * \************************************************************/ uint8_t YST93xTune(uint16_t frequency) { uint16_t fpd = 0; uint8_t i = 0; uint8_t r[3]; unsigned long IFCounter = 0; switch(band) { case YST93x_BAND_FM: //fpd = (frequency + FI)/(50 * 2);//частота и так уже задана в кГц/100, поэтому ниже правильно fpd = (frequency + 107); // частота перестройки 50 Кгц R3 R2 R1 R0 // __________________________ 0 0 0 1 //fpd = (frequency + 107) * 5 ; // 10 Кгц 1 0 0 0 break; case YST93x_BAND_AM: // AM: fpd = ((frequency + FI) / 10) << 4 fpd = (frequency + 45) << 4; break; default: return 1; } YST93xSetMode(YST93x_MUTE); // YST93x only injects FI signal into the PLL when in MUTE mode // Reset the IF counter and program the Frequency Programmable Divider (fpd) bitClear(pll_in1[0], IN10_CTE); pll_in1[1] = byte(fpd >> 8); // старший байт настройки частоты, сдвигаем побитово значения на 8 байт влево pll_in1[2] = byte(fpd & 0x00ff); // младший ший байт, операцией Побитовое И (&) обнуляем значения ст. разрядов ccb.write(0x82, pll_in1, 3); // 0x82, pll_in1[0] -> pll_in1[2] // буфер вывернут в библиотеке, поетому выводится наоборот // pll_in1[2], pll_in1[1], pll_in1[0] // выводим показания частоты в Serial порт Serial.println((FMFrequency < 1000) ? 4 : 3, 0); Serial.print((float)FMFrequency / 10, 2); // Start the IF counter bitSet(pll_in1[0], IN10_CTE); ccb.write(0x82, pll_in1, 3); // Wait for PLL to be locked (DO0_UL == 1) while(i < 20) { delay(50); ccb.read(0xa2, r, 3); // Discard the 1st result: it is latched from the last count (as said on the datasheet) ccb.read(0xa2, r, 3); // The 20 rightmost bits from r[0..2] are the IF counter result i = (bitRead(r[0], DO0_UL)) ? 100 : i + 1; } YST93xSetMode(YST93x_UNMUTE); // Mute off / normal tuner mode if(i == 100) { // PLL is locked. If the IF deviation is within the defined (window) interval, // the radio is likely to be tuned. // Note: this "tuned" detection method is not recommended on the LC72131 datasheet as // it can give false positive results. A better approach would be to get the "tuned" // flag from a RDS decoder with signal quality detection (e.g.: PT2579 or Philips SAA6588) // connected to the YST93x tuner module "RDS Output" pin. SAA6588 is more powerful/popular, // but PT2579 looks a lot easier to use as it is not programmable and has a dedicated // signal quality output pin. IFCounter = (r[0] & 0x0f); IFCounter = (IFCounter << 16) | (unsigned long)(r[1] << 8) | (r[2]); //Serial.println(IFCounter); switch(band) { case YST93x_BAND_FM: // Expected value: IF (10.7MHz) * Mesurement period (32ms, as set via GT[1..0]) = 342400 if((IFCounter > 342400) && ((IFCounter - 342400) < FM_TUNED_WINDOW)) return 1; if((IFCounter < 342400) && ((342400 - IFCounter) < FM_TUNED_WINDOW)) return 1; break; case YST93x_BAND_AM: // Expected value: IF (450kHz) * Mesurement period (8ms, as set via GT[1..0]) = 3600 // Note: scan mode in AM is really poor. I have done my best in tweaking it, but it barely works if((IFCounter > 3600) && ((IFCounter - 3600) < AM_TUNED_WINDOW)) return 1; if((IFCounter < 3600) && ((3600 - IFCounter) < AM_TUNED_WINDOW)) return 1; break; } } return 0; } /**************************************************\ * YST93xIsStereo() * * Returns 1 if the tuned radio station is stereo * \**************************************************/ uint8_t YST93xIsStereo() { uint8_t r[3]; ccb.read(0xa2, r, 3); return(bitRead(r[0], DO0_IN2) ? 0 : 1); } /*******************************************************\ * getKey() * * Read the (analog) keypad. * * If you are using an digital (one key per input pin) * * keypad, just this function to return the correct * * values * \*******************************************************/ uint8_t getKey(uint8_t keypadPin) { uint16_t keypad; uint8_t key = KEY_NONE; keypad = analogRead(keypadPin); if(keypad < 800) key = KEY_BAND; if(keypad < 650) key = KEY_SCAN_DOWN; if(keypad < 500) key = KEY_DOWN; if(keypad < 300) key = KEY_UP; if(keypad < 60) key = KEY_SCAN_UP; // if(keypad < 1000) Serial.println(keypad); // проверка кнопок return key; } /*******************\ * Arduino setup() * \*******************/ void setup() { lcd.begin(16, 2); Serial.begin(19200); ccb.init(); delay(1000); YST93xInit(); YST93xSetMode(YST93x_BAND_FM); tuned = YST93xTune(FMFrequency); } /******************\ * Arduino loop() * \******************/ void loop() { uint8_t scan = 0; int8_t delta = 0; uint8_t key = getKey(KEYPAD_PIN); lcd.setCursor(0, 0); switch(band) { case YST93x_BAND_FM: lcd.print("FM "); lcd.setCursor((FMFrequency < 1000) ? 4 : 3, 0); lcd.print((float)FMFrequency / 10, 1); lcd.print("MHz "); break; case YST93x_BAND_AM: lcd.print("AM "); lcd.setCursor((AMFrequency < 100) ? 4 : 3, 0); lcd.print(AMFrequency * 10); lcd.print("KHz "); break; } // Updates the Stereo indicator lcd.setCursor(12, 0); if(YST93xIsStereo()) lcd.print("[ST]"); else lcd.print("[ ]"); // The "Tuned" indicator is updated only when the station changes lcd.setCursor(2, 1); if(tuned) lcd.print(" Tuned "); else lcd.print(" "); // Processo keypad inputs if(key != KEY_NONE) { switch(key) { case KEY_UP: scan = 0; delta = +1; break; case KEY_DOWN: scan = 0; delta = -1; break; case KEY_SCAN_UP: scan = 1; delta = +1; break; case KEY_SCAN_DOWN: scan = 1; delta = -1; break; case KEY_BAND: switch(band) { case YST93x_BAND_FM: YST93xSetMode(YST93x_BAND_AM); tuned = YST93xTune(AMFrequency); break; case YST93x_BAND_AM: YST93xSetMode(YST93x_BAND_FM); tuned = YST93xTune(FMFrequency); break; } } if(scan) { lcd.setCursor(2, 1); lcd.print("Scanning..."); } // Change the station switch(band) { case YST93x_BAND_FM: do{ FMFrequency += delta; if(FMFrequency > 1080) FMFrequency = 880; if(FMFrequency < 880) FMFrequency = 1080; tuned = YST93xTune(FMFrequency); lcd.setCursor(3, 0); if(FMFrequency < 1000) lcd.print(' '); lcd.print((float)FMFrequency / 10, 1); } while(scan && (! tuned)); break; case YST93x_BAND_AM: do{ AMFrequency += delta; if(AMFrequency > 170) AMFrequency = 53; if(AMFrequency < 53) AMFrequency = 170; tuned = YST93xTune(AMFrequency); lcd.setCursor(3, 0); if(AMFrequency < 100) lcd.print(' '); lcd.print(AMFrequency * 10); } while(scan && (! tuned)); break; } // switch } // if(key) }Благодарю DIVGENY!
Я видел Ваш проект под тюнер в котором используеться приемник на 24 ножках LA1831. Это высший пилотаж!!!
Для меня любителя, (из-за отсутствия знаний) такой проект пока недоступен для понимания. (Постараюсь изучить и на это уйдет время). Его то (времени) как правило и не хватает, поскольку придется погружаться в "тонкости".
В более широком смысле это направление, - использование платформы Arduino (и не только) для "стандартных тюнеров" радиоприемных устройств весьма интересно и познавательно. Многие подбные устройства, - FM/AM и TV тюнерa (от спутниковых до эфирных) уже давно лежат в мусорных ведрах на разборке (стоимость копейки,- возможности широченные). И представляют "академический" интерес, реализованный на практике. К сожалению ни один ВУЗ таких знаний не дает. Страницы форума, это бесценные знания. Низкий поклон Вам!!!
Соображения по использованию других платформ, в некоторых старых CD, DVD используются контроллеры с еще более могучими возможностями, например H8/3000.
С уважением!