Генератор для катушки Мишина

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

megavolt0 пишет:
За исцеления от хвори настойками и отварами когда-то на костре, говорят, жгли... Колдовство! Интересно было бы посмотреть, как бы Клапауций 003 инквизиции рассказывал про электричество и ФМРТ....

а, сейчас за что тебя жгут, просветитель хренов!?

lightwait
Offline
Зарегистрирован: 26.06.2019

Андрэ! Тогда надо заняться чем0-то другим))))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lightwait пишет:
Андрэ! Тогда надо заняться чем0-то другим))))

был бы он программист, то просто бы бухал, а у него масса дел, яблоки вон подошли, кальвадос и оболю не ждёт...

АндрейS
Offline
Зарегистрирован: 13.04.2018

Одно другому не мешает. Катушку буду прикладывать к башке тем кто Диспезу читать не хочет)))))))) Мне сама идея нравиться, что люди что делают, деляться друг с другом. Я то по аптекам не хожу а оказываются туда по 3-5 т.р. могут за раз относить. Я там перекись для плат покупал и настойку прополиса, еще не купил прополис у пасечника чтобы свою сделать.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

АндрейS пишет:

Одно другому не мешает. Катушку буду прикладывать к башке тем кто Диспезу читать не хочет)))))))) Мне сама идея нравиться, что люди что делают, деляться друг с другом. Я то по аптекам не хожу а оказываются туда по 3-5 т.р. могут за раз относить. Я там перекись для плат покупал и настойку прополиса, еще не купил прополис у пасечника чтобы свою сделать.

а источник прополиса кстати это тополь и возможно осина )))

АндрейS
Offline
Зарегистрирован: 13.04.2018

Нас с сестрой мать в детстве лечила прополисом на спирту и еще банка с травами то ли на водке толи на спирту на все случаи жизни. И еще банки были на спину, и горчичники)) Но сестра поумнела и прозрела, не прочь побаловаться антибиотиками, дочь лечит антибиотиками, прям не сестра мне.

AndreiE
Offline
Зарегистрирован: 27.01.2019

AJGrupp пишет:

АндрейS,

эко Вас занесло... "Эффект СТАДА" - он такой, отшибает самостоятельное мышление.

Когда чуток успокоитесь, гляньте одноминутное видео, может дойдёт. Обратите внимание, на 5 Вольт при 20 мА

https://www.youtube.com/watch?v=3_1BvnsPDRM

AJGrupp, правильно ли я понимаю, что на выложенном Вами видео именно то, о чём говорит Мишин?:

"... Физического схлопывания в центр ... Нужно сделать сдвигом фазы ... Второй объект это динамическая (?. невнятно) внешняя среда, которая схлопывается...".

Я в теме катушек Мишина с самого первого упоминания в Интернете. И ни разу не видел, чтобы сам Мишин или или кто-то из сообщества наглядно продемонстрировал. Только на словах.

Почему так? В чем тут проблема?

 

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

megavolt0 пишет:
ua6em пишет:

megavolt0 пишет:

3) MAX471

это второе, что я пробовал, отказался, тоже цифровой фильтр применял, но первого порядка, сильно скакали показания, в абсолютных величинах единиц 10
На сегодняшний день INA219 самый стабильный вариант, в моих заказах на десяток - 2-3 неисправных было, да и INA удобней своим интерфейсом и, всё таки это законченное микропроцессорное устройство )))

да, программирование для меня просто хобби, так что пользовался  "подсказкой зала" велика вероятность, что просто не одолел )))

Я заказал по одной и ту и ту. Посмотрим, с кем отношения сложаться)) Тут скорее проблема не в самой МAХе, а в АЦП меги. Очень "чувствительны" к трасировке, фильтрации и питанию....

может пока идут запчасти на программой удержания частоты поразмышляете?

megavolt0
Offline
Зарегистрирован: 19.07.2019

ua6em, на работе и в жизни пока перегруз. Да и практика показала, что лучше сразу в железе рабработать. Подложку для катушки в 3d замоделировал, синтсинтезатор почти в руках - в сортировочном центре моего гогорода. Где купить медь 0.5 нашёл. Подразгребу дела и займусь.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Проект на Гитхабе, чтобы были разные версии.

lenvic
Offline
Зарегистрирован: 09.10.2018

Вопрсс к ua6em: ARDUINO UNO

1 Энкодер подключен кнопка-5, управление 6 и 7. Что он делает?

2 Зумер 12, pin INT1-3 шимим 490 Гц. Что это и зачем?

Спасибо за ответ, хочу повторить Ваш проект.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lenvic пишет:

Вопрсс к ua6em: ARDUINO UNO

1 Энкодер подключен кнопка-5, управление 6 и 7. Что он делает?

2 Зумер 12, pin INT1-3 шимим 490 Гц. Что это и зачем?

Спасибо за ответ, хочу повторить Ваш проект.

1. Пока ничего, будет работа с меню.
2. Это такой извращённый способ получения 1 секундных импульсов, суть - выводим ШИМ на пин, по умолчанию это частота 490 герц, так как этот пин привязан к прерыванию, 490 раз в секунду вызывается это прерывание в котором увеличивается значение переменной на единицу, при достижении этого значения инвертируется пин связанный с зуммером, то-есть таким образом зуммер пищит с периодом 1 секунда (если ему надо пищать)

PS способ на самом деле позволяет подобрать наиболее благозвучное звучание зуммера изменяя всего лишь одну константу
 

lenvic
Offline
Зарегистрирован: 09.10.2018

Планируется ли доработка проекта с установкой начала и конца процесса, звукового оповещения?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lenvic пишет:

Планируется ли доработка проекта с установкой начала и конца процесса, звукового оповещения?

да, как раз кнопкой энкодера и будет запускаться

АндрейS
Offline
Зарегистрирован: 13.04.2018

AndreiE пишет:

AJGrupp пишет:

АндрейS,

эко Вас занесло... "Эффект СТАДА" - он такой, отшибает самостоятельное мышление.

Когда чуток успокоитесь, гляньте одноминутное видео, может дойдёт. Обратите внимание, на 5 Вольт при 20 мА

https://www.youtube.com/watch?v=3_1BvnsPDRM

AJGrupp, правильно ли я понимаю, что на выложенном Вами видео именно то, о чём говорит Мишин?:

"... Физического схлопывания в центр ... Нужно сделать сдвигом фазы ... Второй объект это динамическая (?. невнятно) внешняя среда, которая схлопывается...".

Я в теме катушек Мишина с самого первого упоминания в Интернете. И ни разу не видел, чтобы сам Мишин или или кто-то из сообщества наглядно продемонстрировал. Только на словах.

Почему так? В чем тут проблема?

 

 

Всем тайным почитателям творчества AJGrupp посвящается http://arduino.ru/forum/otvlechennye-temy/katushka-mishina-i-ne-tolko-mi...
Для тех кто не в курсе, туда мы ходим мусорить и не только))

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

Приветствую! Супруга попросила собрать девайс. Поизучав инет наткнулся на ваш проект. Пытаюсь повторить но на три раза прочитав тему нак и не пришел к общему знаменателю. Вернее вы перепираясь не пришли. Выписал все но при подключении и опросе 9833 не выдает свой адрес. Это нормально?

Проект от ua6em не компилируется - пишет, что невозможно скомпилировать для этой платы . У меня nano с micro usb. Другой проект из темы заливается но 219 показывает все по нулям и больше не реагирует. Куда двигаться пока не придумал...

Очень жаль, что уже третий месяц у вас в теме тишина. Может я чем-то смогу помочь? не программист. Электронщик больше. Тема заинтересовала. Тем более супруге помощь нужна теперь....

Что скажете, господа форумчане?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Shurchik пишет:

Проект от ua6em не компилируется - пишет, что невозможно скомпилировать для этой платы . У меня nano с micro usb. Другой проект из темы заливается но 219 показывает все по нулям и больше не реагирует. Куда двигаться пока не придумал...

Очень жаль, что уже третий месяц у вас в теме тишина. Может я чем-то смогу помочь? не программист. Электронщик больше. Тема заинтересовала. Тем более супруге помощь нужна теперь....

Что скажете, господа форумчане?

скажу так, сделай по быстрому на XR2206 с ручной настройкой тока, ток надо по максимумому  (600ма - 1 ампер) но короткие экспозиции, минут по 10-15, так только в сон потянуло, выключать, подключать иммуномодуляторы, мёд, красная икра, любые естественные бады...

Скетч не выложу, не моя собственность, в разработке новый, он работает на макетке, на AD9833...
Какой именно не компилируется и под какой версией IDE?

Библиотека отсутствующая в папке скетча

wpd123
Offline
Зарегистрирован: 24.03.2019

Shurchik пишет:

Что скажете, господа форумчане?

Сделай на ХR2206, вот схему нашёл в сети. Если пищалка не нужна, то можно не ставить. Это видимо к китайскому таймеру схема генератора, раз бузер всунули.

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

ua6em пишет:

скажу так, сделай по быстрому на XR2206 с ручной настройкой тока, ток надо по максимумому  (600ма - 1 ампер) 

Скетч не выложу, не моя собственность, в разработке новый, он работает на макетке, на AD9833...
Какой именно не компилируется и под какой версией IDE?

я с удовольствием бы, но в нашей глуши 2206 вообще не найти. Проще было выписать с китая 9833. 

Собрал тоже на макетке. не заливается ваш скетч с гигхаба. 1.8.10 (пробовал разные)

Есть один человек ардуинщик до глубины как говориться, но очень уж занят. Хотя данным проектом я его заинтересовал - очень надеюсь и он присоединится...

C:\Users\1C28~1\AppData\Local\Temp\arduino_build_272562\libraries\Adafruit_MCP4725\Adafruit_MCP4725.cpp.o (symbol from plugin): In function `Adafruit_MCP4725::Adafruit_MCP4725()':

(.text+0x0): multiple definition of `Adafruit_MCP4725::Adafruit_MCP4725()'

C:\Users\1C28~1\AppData\Local\Temp\arduino_build_272562\sketch\Adafruit_MCP4725.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\1C28~1\AppData\Local\Temp\arduino_build_272562\libraries\Adafruit_MCP4725\Adafruit_MCP4725.cpp.o (symbol from plugin): In function `Adafruit_MCP4725::Adafruit_MCP4725()':

(.text+0x0): multiple definition of `Adafruit_MCP4725::Adafruit_MCP4725()'

C:\Users\1C28~1\AppData\Local\Temp\arduino_build_272562\sketch\Adafruit_MCP4725.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\1C28~1\AppData\Local\Temp\arduino_build_272562\libraries\Adafruit_MCP4725\Adafruit_MCP4725.cpp.o (symbol from plugin): In function `Adafruit_MCP4725::Adafruit_MCP4725()':

(.text+0x0): multiple definition of `Adafruit_MCP4725::begin(unsigned char)'

C:\Users\1C28~1\AppData\Local\Temp\arduino_build_272562\sketch\Adafruit_MCP4725.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\1C28~1\AppData\Local\Temp\arduino_build_272562\libraries\Adafruit_MCP4725\Adafruit_MCP4725.cpp.o (symbol from plugin): In function `Adafruit_MCP4725::Adafruit_MCP4725()':

(.text+0x0): multiple definition of `Adafruit_MCP4725::setVoltage(unsigned int, bool)'

C:\Users\1C28~1\AppData\Local\Temp\arduino_build_272562\sketch\Adafruit_MCP4725.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

Несколько библиотек найдено для "Adafruit_MCP4725.h"
 Используется: C:\Program
Не используется: C:\Program
Несколько библиотек найдено для "Wire.h"
 Используется: C:\Program
Не используется: C:\Program
Несколько библиотек найдено для "SPI.h"
 Используется: C:\Program
Используем библиотеку Wire версии 1.0 из папки: C:\Program Files
Используем библиотеку SPI версии 1.0 из папки: C:\Program Files
Используем библиотеку Adafruit_MCP4725 версии 1.0.2 из папки: C:\Program Files
exit status 1
Ошибка компиляции для платы Arduino Nano.

 

wpd123
Offline
Зарегистрирован: 24.03.2019

Так XR2206 тоже с Китая все выписываем, так как у нас например цену ломят 150р. за штуку, с Китая я за 150 руб. 5 штук покупал. 

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

wpd123 пишет:

Так XR2206 тоже с Китая все выписываем, так как у нас например цену ломят 150р. за штуку, с Китая я за 150 руб. 5 штук покупал. 

Выписал... но когда прийдет... хотел на ардуинке собрать. Собрал но пнр не выходят...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

у меня в 1.8.10 компилируется, немного поругался, но всё ок
 

C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.1\libraries\Wire\src\utility\twi.c: In function '__vector_24':

C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.1\libraries\Wire\src\utility\twi.c:447:49: warning: this statement may fall through [-Wimplicit-fallthrough=]

       twi_masterBuffer[twi_masterBufferIndex++] = TWDR;

                                                 ^

C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.1\libraries\Wire\src\utility\twi.c:448:5: note: here

     case TW_MR_SLA_ACK:  // address sent, ack received

     ^~~~

C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.1\libraries\Wire\src\utility\twi.c:529:9: warning: this statement may fall through [-Wimplicit-fallthrough=]

       if(0 == twi_txBufferLength){

         ^

C:\Users\User\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.1\libraries\Wire\src\utility\twi.c:534:5: note: here

     case TW_ST_DATA_ACK: // byte sent, ack returned

     ^~~~

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

wpd123 пишет:

Так XR2206 тоже с Китая все выписываем, так как у нас например цену ломят 150р. за штуку, с Китая я за 150 руб. 5 штук покупал. 

у нас 400 -450 за штуку, XR2206 дешёвые из китая 50 штук 100% брак, деньги не вернули, брал внук приятеля, сказал фигня заморачиваться с возвратом )))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Shurchik пишет:

wpd123 пишет:

Так XR2206 тоже с Китая все выписываем, так как у нас например цену ломят 150р. за штуку, с Китая я за 150 руб. 5 штук покупал. 

Выписал... но когда прийдет... хотел на ардуинке собрать. Собрал но пнр не выходят...

ina219 тоже много брака, меньше чем по 3 штуки лучше не брать

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

219 живая. Запустил. Меряет верно. Поправил везде все имена и места расположения, залился скет но на 40кHz так и стоит. ни на что не реагирует. Куда дальше копать?9833 что-то молчит... отсюда https://tsibrov.blogspot.com/2018/06/ad9833.html взял скетч на проверку, переназначил энкодер - по дисплею все отражает но на выходе тишина. вместо катушки подключил небольшой динамик. при касании 3 вывода - 50 герц наводится.

Большое подозрение, что 9833 мертвая. Как можно еще 100% проверить, что живая? Сканером должен определяться ее адрес или просто прописываем в нее значения и все?

Опять же на энкодер никакой реакции. Ни на нажатие ни на прокрутки...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

проверить сканером адрес, у меня неисправных не было, программа энкодера еще не написана )))

PS Вы там с тором поосторожнее, делайте классическую

wpd123
Offline
Зарегистрирован: 24.03.2019

Пришли с Китая 5 штук XR2206, все бракованые, наверное специально отбраковывают и на развес продают в Россию, так как ни чем не докажешь им, что не ты её спалил. Брал готовые генераторы у них, все работают. То есть генераторы КИТ, они комплектуют рабочими микрухами, а когда заказывашь одни микрухи, кладут тебе заведомый брак! Теперь если и буду заказывать, то буду продавцов предупреждать, что извлечение микросхем с посылки будет сниматься на видео, вполть до установке их в панельку  рабочего генератора, вместе с осциллограммой, которую эти микросхемы на нём выдадут, (или не выдадут). И это видео будет доказательством в споре, ежели они положат брак, то деньги им придётся вернуть. Пусть думают перед тем,как брак отправлять.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

по XR2206 есть проверенный продавец, были 100% исправные, но это не самые дешёвые микросхемы

wpd123
Offline
Зарегистрирован: 24.03.2019

Ссылочку на него можно?

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

ua6em пишет:

проверить сканером адрес, у меня неисправных не было, программа энкодера еще не написана )))

PS Вы там с тором поосторожнее, делайте классическую

в 625 посте ссылка. понравилось как там реализован энкодер.

Сканер ничего не находит. сегодня выпаяю и отдельно буду пробовать.

Начало 3 дня тор а далее классика.

Подскажите - второй энкодер для чего?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

про энкодер, пока не понятно, для чего он нужен, изначально предполагалось, что можно залить скетч генератора на ad9833.
Не сформировано требований, что будет реализовано для ручного режима, а автоматика работает и без него )))

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

Кручение перебирает меню.

1. автоматический / ручной режим. выбор частоты резонанса в ручную

2. выбор синуса - меандра  можно и (типа катушки)

3. таймер сколько минут

4. мощность излучения

5. отключение подсветки дисплея в минутах, работа с бузером  и т.д.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Да, таймер пожалуй нужен...мощность...пожалуй, но тогда и уровень гармоник снижается, но сдаётся мне что они там что-то значат...

Надо выработать консенсунс )))

ingfa
Offline
Зарегистрирован: 15.09.2018

   К удалению

AndreySS
Offline
Зарегистрирован: 15.10.2019

   ingfa, https://yadi.sk/d/8X1azfziMW01Pg это последнее что я делал и выкладывал, на схеме все модули какие нужны подписаны, там код от автора темы и библиотеки которые у меня компилировались. Ua6em, говрил что еще один нужен энкодер, активная пищалка и MCP4725. В 405 посту есть схема Alp и там он пишет про резистор который нужен чтобы исправить обрезанный синус. Так же с этой схемой работает код Владимира Циброва https://tsibrov.blogspot.com/2018/06/ad9833.html 
вот код:

#include <SPI.h>
// ***** I2C дисплей *****
#include <LiquidCrystal_I2C.h> // https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
#define cols 20
#define rows 4
LiquidCrystal_I2C lcd(0x27, cols, rows);
char *Blank;

// ********** AD9833 **********
#define bMode 0x2
#define bDiv2 0x8
#define bOpbiten 0x20
#define bSleep12 0x40
#define bSleep1 0x80
#define bReset 0x100
#define bHLB 0x1000
#define bB28 0x2000
#define bCntrl_reg 0x0
#define bFreq_reg0 0x4000
#define bFreq_reg1 0x8000
#define bPhase_reg 0xC000

unsigned long Freq;
unsigned long FreqStep;
int Phase;
enum eWaveForm {wfSin, wfTri, wfSqr, wfSqr2};
eWaveForm WaveForm;

// ********** Параметры меню **********
#define ShowScrollBar 1     // Показывать индикаторы прокрутки (0/1)
#define ScrollLongCaptions 1// Прокручивать длинные названия (0/1)
#define ScrollDelay 800     // Задержка при прокрутке текста
#define BacklightDelay 20000// Длительность подсветки
#define ReturnFromMenu 1    // Выходить из меню после выбора элемента(0/1)

enum eMenuKey {mkNull, mkBack, mkRoot, mkSetFreq, mkSetPhase, mkForm, mkSin, mkTri, mkSquare,
               mkSquareDiv2, mkInc, mkInc1, mkInc10, mkInc100, mkInc1000, mkAbout
              };

// ********** Переменные для энкодера ***************
#define pin_CLK 6 // Энкодер пин A
#define pin_DT  5 // Энкодер пин B
#define pin_Btn 4 // Кнопка

unsigned long CurrentTime, PrevEncoderTime;
enum eEncoderState {eNone, eLeft, eRight, eButton};
eEncoderState EncoderState;
int EncoderA, EncoderB, EncoderAPrev, counter;
bool ButtonPrev;

// ********** Прототипы функций ***************
eEncoderState GetEncoderState();
void LCDBacklight(byte v = 2);
eMenuKey DrawMenu(eMenuKey Key);

// ******************** Меню ********************
byte ScrollUp[8]  = {0x4, 0xa, 0x11, 0x1f};
byte ScrollDown[8]  = {0x0, 0x0, 0x0, 0x0, 0x1f, 0x11, 0xa, 0x4};

byte ItemsOnPage = rows;    // Максимальное количество элементов для отображения на экране
unsigned long BacklightOffTime = 0;
unsigned long ScrollTime = 0;
byte ScrollPos;
byte CaptionMaxLength;

struct sMenuItem {
  eMenuKey  Parent;       // Ключ родителя
  eMenuKey  Key;          // Ключ
  char      *Caption;     // Название пункта меню
  void      (*Handler)(); // Обработчик
};

sMenuItem Menu[] = {
  {mkNull, mkRoot, "Menu", NULL},
    {mkRoot, mkSetFreq, "Set frequency", NULL},
    {mkRoot, mkSetPhase, "Set phase", NULL},
    {mkRoot, mkForm, "Set wave form", NULL},
      {mkForm, mkSin, "Sinusoidal", NULL},
      {mkForm, mkTri, "Triangular", NULL},
      {mkForm, mkSquare, "Square", NULL},
      {mkForm, mkSquareDiv2, "Square F/2", NULL},
      {mkForm, mkBack, "Back", NULL},
    {mkRoot, mkInc, "Set frequency increment value", NULL},
      {mkInc, mkInc1, "1 HZ", NULL},
      {mkInc, mkInc10, "10 HZ", NULL},
      {mkInc, mkInc100, "100 HZ", NULL},
      {mkInc, mkInc1000, "1000 HZ", NULL},
      {mkInc, mkBack, "Back", NULL},
    {mkRoot, mkAbout, "About", NULL},
    {mkRoot, mkBack, "Back", NULL}
};

const int MenuLength = sizeof(Menu) / sizeof(Menu[0]);

void LCDBacklight(byte v) { // Управление подсветкой
  if (v == 0) { // Выключить подсветку
    BacklightOffTime = millis();
    lcd.noBacklight();
  }
  else if (v == 1) { //Включить подсветку
    BacklightOffTime = millis() + BacklightDelay;
    lcd.backlight();
  }
  else { // Выключить если время вышло
    if (BacklightOffTime < millis())
      lcd.noBacklight();
    else
      lcd.backlight();
  }
}

eMenuKey DrawMenu(eMenuKey Key) { // Отрисовка указанного уровня меню и навигация по нему
  eMenuKey Result;
  int k, l, Offset, CursorPos, y;
  sMenuItem **SubMenu = NULL;
  bool NeedRepaint;
  String S;
  l = 0;
  LCDBacklight(1);
  // Запишем в SubMenu элементы подменю
  for (byte i = 0; i < MenuLength; i++) {
    if (Menu[i].Key == Key) {
      k = i;
    }
    else if (Menu[i].Parent == Key) {
      l++;
      SubMenu = (sMenuItem**) realloc (SubMenu, l * sizeof(void*));
      SubMenu[l - 1] = &Menu[i];
    }
  }

  if (l == 0) { // l==0 - подменю нет
    if ((ReturnFromMenu == 0) and (Menu[k].Handler != NULL)) (*Menu[k].Handler)(); // Вызываем обработчик если он есть
    LCDBacklight(1);
    return Key; // и возвращаем индекс данного пункта меню
  }

  // Иначе рисуем подменю
  CursorPos = 0;
  Offset = 0;
  ScrollPos = 0;
  NeedRepaint = 1;
  do {
    if (NeedRepaint) {
      NeedRepaint = 0;
      lcd.clear();
      y = 0;
      for (int i = Offset; i < min(l, Offset + ItemsOnPage); i++) {
        lcd.setCursor(1, y++);
        lcd.print(String(SubMenu[i]->Caption).substring(0, CaptionMaxLength));
      }
      lcd.setCursor(0, CursorPos);
      lcd.print(">");
      if (ShowScrollBar) {
        if (Offset > 0) {
          lcd.setCursor(cols - 1, 0);
          lcd.write(0);
        }
        if (Offset + ItemsOnPage < l) {
          lcd.setCursor(cols - 1, ItemsOnPage - 1);
          lcd.write(1);
        }
      }
    }
    EncoderState = GetEncoderState();
    switch (EncoderState) {
      case eLeft: {
          // Прокрутка меню вверх
          LCDBacklight(1);
          ScrollTime = millis() + ScrollDelay * 5;
          if (CursorPos > 0) {  // Если есть возможность, поднимаем курсор
            if ((ScrollLongCaptions) and (ScrollPos)) {
              // Если предыдущий пункт меню прокручивался, то выводим его заново
              lcd.setCursor(1, CursorPos);
              lcd.print(Blank);
              lcd.setCursor(1, CursorPos);
              lcd.print(String(SubMenu[Offset + CursorPos]->Caption).substring(0, CaptionMaxLength));
              ScrollPos = 0;
            }
            // Стираем курсор на старом месте, рисуем в новом
            lcd.setCursor(0, CursorPos--);
            lcd.print(" ");
            lcd.setCursor(0, CursorPos);
            lcd.print(">");
          }
          else if (Offset > 0) {
            //Курсор уже в крайнем положении. Если есть пункты выше, то перерисовываем меню
            Offset--;
            NeedRepaint = 1;
          }
          break;
        }
      case eRight: {
          // Прокрутка меню вниз
          LCDBacklight(1);
          ScrollTime = millis() + ScrollDelay * 5;
          if (CursorPos < min(l, ItemsOnPage) - 1) {// Если есть возможность, то опускаем курсор
            if ((ScrollLongCaptions) and (ScrollPos)) {
              // Если предыдущий пункт меню прокручивался, то выводим его заново
              lcd.setCursor(1, CursorPos);
              lcd.print(Blank);
              lcd.setCursor(1, CursorPos);
              lcd.print(String(SubMenu[Offset + CursorPos]->Caption).substring(0, CaptionMaxLength));
              ScrollPos = 0;
            }
            // Стираем курсор на старом месте, рисуем в новом
            lcd.setCursor(0, CursorPos++);
            lcd.print(" ");
            lcd.setCursor(0, CursorPos);
            lcd.print(">");
          }
          else {
            // Курсор уже в крайнем положении. Если есть пункты ниже, то перерисовываем меню
            if (Offset + CursorPos + 1 < l) {
              Offset++;
              NeedRepaint = 1;
            }
          }
          break;
        }
      case eButton: {
          // Выбран элемент меню. Нажатие кнопки Назад обрабатываем отдельно
          LCDBacklight(1);
          ScrollTime = millis() + ScrollDelay * 5;
          if (SubMenu[CursorPos + Offset]->Key == mkBack) {
            free(SubMenu);
            return mkBack;
          }
          Result = DrawMenu(SubMenu[CursorPos + Offset]->Key);
          if ((Result != mkBack) and (ReturnFromMenu)) {
            free(SubMenu);
            return Result;
          }
          NeedRepaint = 1;
          break;
        }
      case eNone: {
          if (ScrollLongCaptions) {
            // При бездействии прокручиваем длинные названия
            S = SubMenu[CursorPos + Offset]->Caption;
            if (S.length() > CaptionMaxLength)
            {
              if (ScrollTime < millis())
              {
                ScrollPos++;
                if (ScrollPos == S.length() - CaptionMaxLength)
                  ScrollTime = millis() + ScrollDelay * 2; // Небольшая задержка когда вывели все название
                else if (ScrollPos > S.length() - CaptionMaxLength)
                {
                  ScrollPos = 0;
                  ScrollTime = millis() + ScrollDelay * 5; // Задержка перед началом прокрутки
                }
                else
                  ScrollTime = millis() + ScrollDelay;
                lcd.setCursor(1, CursorPos);
                lcd.print(Blank);
                lcd.setCursor(1, CursorPos);
                lcd.print(S.substring(ScrollPos, ScrollPos + CaptionMaxLength));
              }
            }
          }
          LCDBacklight();
        }
    }
  } while (1);
}
//****************************************

void setup() {
  pinMode(pin_CLK, INPUT);
  pinMode(pin_DT,  INPUT);
  pinMode(pin_Btn, INPUT_PULLUP);
  SPI.begin();
  lcd.begin();
  lcd.backlight();
  CaptionMaxLength = cols - 1;
  Blank = (char*) malloc(cols * sizeof(char));
  for (byte i = 0; i < CaptionMaxLength; i++)
    Blank[i] = ' ';
  if (ShowScrollBar) {
    CaptionMaxLength--;
    lcd.createChar(0, ScrollUp);
    lcd.createChar(1, ScrollDown);
  }
  Blank[CaptionMaxLength] = 0;
  FreqStep = 1000; // Шаг смены частоты
  WaveForm = wfSin;
  WriteAD9833(bCntrl_reg | bReset | bB28);
  SetFrequency(300000); // Установим частоту Гц
  SetPhase(0); // Сдвиг по фазе 0
  WriteAD9833(bCntrl_reg | bB28); // Снимаем Reset
  LCDRepaint(); // Выведем текущие параметры на дисплей
  LCDBacklight(1); // Включаем подвсветку
}

void loop() {
  unsigned long F;
  // В цикле опрашиваем энкодер
  switch (GetEncoderState()) {
    case eNone: { // При бездействии отключаем подсветку по таймауту
        LCDBacklight();
        return;
      }
    case eLeft: { // Уменьшить частоту
        LCDBacklight(1); // Включаем подсветку
        if (Freq == 1) return; // Меньше уже некуда
        if (Freq > FreqStep)
          SetFrequency(Freq - FreqStep);
        else
          SetFrequency(1);
        break;
      }
    case eRight: { // Увеличить частоту
        LCDBacklight(1); // Включаем подсветку
        if (Freq == 12500000) return; // Больше уже некуда
        if (Freq + FreqStep <= 12500000)
          SetFrequency(Freq + FreqStep);
        else
          SetFrequency(12500000);
        break;
      }
    case eButton: { // При нажатии на кнопку показываем меню
        LCDBacklight(1); // Включаем подсветку
        switch (DrawMenu(mkRoot)) { // Показываем меню и анализируем выбранный пункт
          case mkSetFreq: { // Установить новое значение частоты
              F = InputFreq(); // Запрашиваем новое значение
              while ((F > 12500000) or (F < 1)) {
                // Частота должна быть в диапазоне 1...12500000Гц
                lcd.clear();
                lcd.print("Frequency should be");
                lcd.setCursor(0, 1);
                lcd.print("between 1Hz and");
                lcd.setCursor(0, 2);
                lcd.print("12.5Mhz");
                while (GetEncoderState() == eNone);
                F = InputFreq(); // Предлагаем ввести частоту повторно
              }
              if (F != Freq)
                SetFrequency(F); // Устанавливаем новое значение частоты
              break;
            }
          case mkSetPhase:   { // Установить фазу
              SetPhase(InputPhase());
              break;
            }
          case mkSin:        { // Изменить форму сигнала на синусоидальную
              SetForm(wfSin);
              break;
            }
          case mkTri:        { // ... треугольную
              SetForm(wfTri);
              break;
            }
          case mkSquare:     { // ... прямоугольную
              SetForm(wfSqr);
              break;
            }
          case mkSquareDiv2: { // ... прямоугольную с делителем на 2
              SetForm(wfSqr2);
              break;
            }
          case mkInc1:    {    // Установить приращение частоты 1Гц
              FreqStep = 1;
              break;
            }
          case mkInc10:   {
              FreqStep = 10;  // 10Гц
              break;
            }
          case mkInc100:  {
              FreqStep = 100; // 100Гц
              break;
            }
          case mkInc1000: {
              FreqStep = 1000;// 1000Гц
              break;
            }
          case mkAbout: {
              lcd.clear();
              lcd.print("AD9833 generator");
              lcd.setCursor(0, 1);
              lcd.print("tsibrov.blogspot.com");
              while (GetEncoderState() == eNone){
                LCDBacklight();
              }
              LCDBacklight(1);
              break;
            }
        }
        // После выхода из меню перерисовываем главный экран
        LCDRepaint();
        return;
      }
  }
  // Обновить значение частоты
  lcd.setCursor(0, 0);
  lcd.print(Blank);
  lcd.setCursor(0, 0);
  lcd.print("Freq:  ");
  lcd.print(Freq);
  lcd.print("Hz");
}

// ******************** Вывод информации на дисплей ********************
void LCDRepaint() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Freq:  ");
  lcd.print(Freq);
  lcd.print("Hz");
  lcd.setCursor(0, 1);
  lcd.print("Phase: ");
  lcd.print(Phase);
  lcd.print("Deg");
  lcd.setCursor(0, 2);
  lcd.print("Form:  ");
  switch (WaveForm) {
    case wfSin: {
        lcd.print("Sinusoidal");
        break;
      }
    case wfTri: {
        lcd.print("Triangular");
        break;
      }
    case wfSqr: {
        lcd.print("Square");
        break;
      }
    case wfSqr2: {
        lcd.print("Square F/2");
        break;
      }
  }
}

// ******************** Энкодер с кнопкой ********************
eEncoderState GetEncoderState() {
  // Считываем состояние энкодера
  eEncoderState Result = eNone;
  CurrentTime = millis();
  if (CurrentTime >= (PrevEncoderTime + 5)) {
    PrevEncoderTime = CurrentTime;
    if (digitalRead(pin_Btn) == LOW ) {
      if (ButtonPrev) {
        Result = eButton; // Нажата кнопка
        ButtonPrev = 0;
      }
    }
    else {
      ButtonPrev = 1;
      EncoderA = digitalRead(pin_DT);
      EncoderB = digitalRead(pin_CLK);
      if ((!EncoderA) && (EncoderAPrev)) { // Сигнал A изменился с 1 на 0
        if (EncoderB) Result = eRight;     // B=1 => энкодер вращается по часовой
        else          Result = eLeft;      // B=0 => энкодер вращается против часовой
      }
      EncoderAPrev = EncoderA; // запомним текущее состояние
    }
  }
  return Result;
}

// ******************** Ввод нового значения частоты ********************
unsigned long InputFreq() {
  unsigned long F = Freq;
  int Positions[] = {4, 5, 7, 8, 9, 11, 12, 13};
  int Digits[8];
  int p = 0;
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("Input frequency:");
  lcd.setCursor(14, 1);
  lcd.print("Hz");
  // Разбиваем частоту на разряды и выводим на дисплей
  for (int i = 7; i >= 0; i--) {
    Digits[i] = F % 10;
    lcd.setCursor(Positions[i], 1);
    lcd.print(Digits[i]);
    F = F / 10;
  }
  lcd.setCursor(3, 3);
  lcd.print("OK      Cancel");
  lcd.setCursor(Positions[0], 1);
  lcd.cursor();

  //Основной цикл - выбор разряда для изменения либо OK/Cancel
  while (1)
  {
    EncoderState = GetEncoderState();
    switch (EncoderState) {
      case eNone: {
          LCDBacklight();
          continue;
        }
      case eLeft: { // Двигаем курсор влево
          LCDBacklight(1); // Включаем подсветку
          if (p == 0) continue; // Левее перемещаться некуда
          if (p == 9) { // Выбран Cancel, перемещаемся к OK
            lcd.setCursor(10, 3); lcd.print(' ');
            lcd.setCursor(2, 3);  lcd.print('>');
            p--;
            continue;
          }
          if (p == 8) { // Выбран OK, перемещаемся к частоте
            lcd.setCursor(2, 3); lcd.print(' ');
            p--;
            lcd.setCursor(Positions[p], 1);
            lcd.cursor();
            continue;
          }
          // Выбрана частота, перемещаемся к старшему разряду
          p--;
          lcd.setCursor(Positions[p], 1);
          continue;;
        }
      case eRight: { // Двигаем курсор вправо
          LCDBacklight(1); // Включаем подсветку
          if (p == 9) continue; // Правее перемещаться некуда
          if (p == 8) { // Выбран Ok, перемещаемся к Cancel
            lcd.setCursor(2, 3); lcd.print(' ');
            lcd.setCursor(10, 3); lcd.print('>');
            p++;
            continue;
          }
          if (p == 7) { // Выбран младший разряд частоты, перемещаемся к OK
            lcd.noCursor();
            lcd.setCursor(2, 3); lcd.print('>');
            p++;
            continue;
          }
          // Выбрана частота, перемещаемся к младшему разряду
          p++;
          lcd.setCursor(Positions[p], 1);
          continue;;
        }
      case eButton: { //Нажата кнопка
          LCDBacklight(1); // Включаем подсветку
          if (p == 9) {
            lcd.noCursor();
            return Freq; // Cancel.
          }
          if (p == 8) { // OK. Собираем и возвращаем новое значение частоты
            lcd.noCursor();
            F = 0;
            for (int i = 0; i < 8; i++)
              F = F * 10 + Digits[i];
            return F;
          }
          // Редактирование выбранного разряда частоты
          EncoderState = eNone;
          lcd.setCursor(Positions[p], 1);
          lcd.blink();
          while (EncoderState != eButton)
          {
            EncoderState = GetEncoderState();
            switch (EncoderState) {
              case eNone: {
                  LCDBacklight();
                  continue;
                }
              case eLeft: {
                  LCDBacklight(1); // Включаем подсветку
                  if (Digits[p] == 0) continue;
                  lcd.setCursor(Positions[p], 1);
                  lcd.print(--Digits[p]);
                  lcd.setCursor(Positions[p], 1);
                  continue;
                }
              case eRight: {
                  LCDBacklight(1); // Включаем подсветку
                  if (Digits[p] == 9) continue;
                  lcd.setCursor(Positions[p], 1);
                  lcd.print(++Digits[p]);
                  lcd.setCursor(Positions[p], 1);
                  continue;
                }
            }
          }
          LCDBacklight(1);
          lcd.noBlink();
          continue;
        }
    }
  }
}

// ******************** Ввод фазы ********************
int InputPhase() {
  int w = Phase;
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Input phase shift:");
  lcd.setCursor(6, 1);
  lcd.print(w);
  lcd.print("Deg");
  while (1) {
    EncoderState = GetEncoderState();
    switch (EncoderState) {
      case eNone: {
          LCDBacklight();
          continue;
        }
      case eButton: {
          LCDBacklight(1);
          return w;
      }
      case eLeft: {
          LCDBacklight(1);
          if (w > 0) w--;
          break;
        }
      case eRight: {
          LCDBacklight(1);
          if (w < 360) w++;
          break;
        }
    }
    lcd.setCursor(6, 1);
    lcd.print(w);
    lcd.print("Deg  ");
  }
}

// ******************** Установить частоту ********************
void SetFrequency(unsigned long val) {
  Freq = val;
  unsigned long FreqData = round((float) val * 10.73741 + 0.5);
  WriteAD9833(FreqData & 0x3FFF | bFreq_reg0);
  WriteAD9833((FreqData >> 14) | bFreq_reg0);
}

// ******************** Установить фазу ********************
void SetPhase(int val) {
  Phase = val;
  unsigned long PhaseData = round (float(val) * 11.37777 + 0.5);
  WriteAD9833(PhaseData | bPhase_reg);
}

// ******************** Установить форму ********************
void SetForm(eWaveForm val) {
  WaveForm = val;
  int16_t CntrlData;
  switch (val) {
    case wfSin: {
        CntrlData = 0;
        break;
      }
    case wfTri: {
        CntrlData = bMode;
        break;
      }
    case wfSqr: {
        CntrlData = bOpbiten | bDiv2 | bSleep12;
        break;
      }
    case wfSqr2: {
        CntrlData = bOpbiten | bSleep12;
        break;
      }
  }
  WriteAD9833(CntrlData | bCntrl_reg | bB28);
}

// ******************** Передача 16-битного слова в AD9833 ********************
void WriteAD9833(uint16_t Data) {
  SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE2));
  digitalWrite(SS, LOW);
  delayMicroseconds(1);
  SPI.transfer16(Data);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}

И меня есть предположения что ина 219 сиреневого цвета немного другой формы лучше  чем синее , меньше брака. У Shurchik вроде такая стоит и Alp где тут фото выкладывал.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Для применения только в качестве генератора для катушки Мишина можно добавить в схему пищалку и три светодиода, под таймер на 5,10 и 15 минут...

Да, недорогие и не бракованные XR2206 брал у этого продавца - https://ru.aliexpress.com/item/32842901280.html?spm=2114.13010708.0.0.3a...

 

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

Для чего колхоз если у нас есть 4 строчный дисплей......

 

все-таки моя 9833 не але :( выписал новую..... опять потеря времени...

Может есть у кого? Почтой не отправите?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

таймер в нижнюю строку будем выводить?
Если да, то что там писать?

выписывать надо попарно, одна обычно дохлая, у меня даже на AD9850 в одной умудрились чип перевернуть )))

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

ua6em пишет:

что там писать?

В работе хх минут (а когда менее 1,5 минуты до окончания

В работе xx секунд 

и считает в меньшую сторону. Можно мигующую точку добавить чтобы видно было, что работает

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

понятно, только  дисплей то на латыни )))

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

Да это все тонкости. Есть на крайняк и наши библиотеки...

Вот как вариант но не в этом суть...

AndreySS
Offline
Зарегистрирован: 15.10.2019

кириллица на китайском LSD 2004 https://vk.com/topic-110073626_33452894  ua6em, под ваш код этот способ можно адаптировать?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AndreySS пишет:

кириллица на китайском LSD 2004 https://vk.com/topic-110073626_33452894  ua6em, под ваш код этот способ можно адаптировать?

а як жеж )))

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

ua6em пишет:

а як жеж )))

Отлично. Пока идет новая 9833 может и с энкодерами разберемся?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Попробуем...

AndreySS
Offline
Зарегистрирован: 15.10.2019

Shurchik пишет:

ua6em пишет:

а як жеж )))

Отлично. Пока идет новая 9833 может и с энкодерами разберемся?

ua6em, в той версии платы что у вас под 2 энкодера пины на ардуине не в лучшем порядке был назначенные для травления, я там делал обводы, так как свободы в этом деле не имею я сделал по той схеме что была  наскоряк. Переназначить для более компактной разводки эти пины только в другом порядке или на соседние я думаю это не проблема?
 И в общем я понял что дорожки надо делать как можно толще и все заливать землей, помех чуть чуть меньше будет.
Мне пришли разъемы как на осциллографе и я купил еще разъемы под тюльпаны, и питание. Также обзавелся пищалками и MCP4725 пришла. Все это хозяйство пристрою. В этот раз думаю получиться уже законченная плата под травление!
И транзистор с АД9833 будем ставить чтобы до 1 вольта поднять?

AndreySS
Offline
Зарегистрирован: 15.10.2019

 Shurchik, а у вас  MCP4725 есть?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

1. по переназначению пинов пока не скажу, как там это делалось программно, надо пробовать
2. по пищалке тоже не помню на какой пин выводил, я с кодом бузе соригинальничал, тоже надо смотреть
3. Усиление надо добавить, всё таки режим провала синусоиды надо попробовать реализовать

вообще я приверженец простых решений, включил и пользуйся, таймер пожалуй да, сейчас подключил нажатие кнопки, попробую следующую функцию - короткие нажатия устанавливают таймер по кругу 5-10-15 минут, длинное запускает обратный отсчёт

Shurchik
Shurchik аватар
Offline
Зарегистрирован: 29.09.2019

AndreySS пишет:

 Shurchik, а у вас  MCP4725 есть?


на плате есть и запасная

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

У меня вот такой вопрос, а плату может у Китайцев заказать, чтобы с маской была...цена вопроса вроде не высокая