Амплитуда генератора
- Войдите на сайт для отправки комментариев
Пт, 08/06/2018 - 12:36
<div>Здравствуйте эксперты.</div><div>Вот программа, состоящая из вольтметра переменного напряжения и синусоидального генератора.</div><div>Как сделать амплитуду генератора такую как амплитуда измеряного напряжения ?</div><div> </div>#define SAMPLES 100 #include <libmaple/dma.h> #include <LiquidCrystal.h> #include "EmonLib.h" #include <math.h> LiquidCrystal lcd(PA0, PA1, PA2, PA3, PA4, PA5); EnergyMonitor emon1, emon2, emon3; float volt, avolt[50], sumv; char symbPF = 223; dma_tube_config dma_cfg, dma_cfg2; int flag1 = 0; int out1 = PB7; int val1[SAMPLES]; int16 shift = 0; /////////////////////////////////// int amp = 35; //int amp = volt; ///////////////////////////////////// int cnt = 0; int time_track = 0; float stp = 6.2831 / SAMPLES; int ret = 17; timer_dev *dev1 = PIN_MAP[out1].timer_device; uint8 cc_channel1 = PIN_MAP[out1].timer_channel; void timer_conf() { timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2); timer_dma_set_burst_len(dev1, 1); timer_dma_enable_req(dev1, cc_channel1); timer_set_reload(dev1, 102); timer_set_prescaler(dev1, 0); } void dma_conf() { dma_init(DMA1); /* T4C2 DMA C4 */ dma_cfg.tube_dst = &(dev1->regs.gen->DMAR); dma_cfg.tube_dst_size = DMA_SIZE_32BITS; dma_cfg.tube_src = val1; dma_cfg.tube_src_size = DMA_SIZE_32BITS; dma_cfg.tube_nr_xfers = SAMPLES; dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE; dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2; dma_cfg.target_data = 0; ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg); } void dma_start() { dma_enable(DMA1, DMA_CH4); timer_resume(dev1); } /////////////////////////////////////////////////// void init_wave() { int i; for (i = 0; i < SAMPLES; i++) { val1[i] = 50 + amp * sin(stp * i); } } ////////////////////////////////////////////////////////// void setup() { int i; pinMode(out1, PWM); pinMode(PA7, INPUT); // U lcd.begin(16, 2); // set up the LCD’s number of columns and rows: emon1.voltage(PA6, 3000, 1.7); // Voltage: input pin, calibration, phase_shift U1 emon2.voltage(PA7, 3000, 1.7); emon1.current(PA7, 111.1); // Current Serial.begin(9600); timer_conf(); dma_conf(); dma_start(); init_wave(); } void loop() { sumv = 0; for (int i = 0; i < 50; i++) { emon1.calcVI(20, 200); // Calculate all. No.of half wavelengths (crossings), time-out TM emon2.calcVI(20, 200); avolt[i] = emon1.Vrms; // holds volt value } for (int i = 0; i < 50; i++) { sumv += avolt[i]; } volt = sumv / 50; lcd.setCursor(0, 1); lcd.print("U="); lcd.print(volt); } пробовал так, но не получилось.
int amp = volt;
и
val1[i] = 50 + volt * sin(stp * i);
1. Ну, "не получилось" у Вас потому, что Вы пытались использовать величину volt перед тем, как присвоить ей какое-либо значение. По умолчанию она равна 0, поэтому и на выходе Вы получили амплитуду 0 Вольт.
2. "Сделать амплитуду такой же..." подразумевает регулировку амплитуды в процессе работы, а этого в Вашем коде не предусмотрено. Определитесь, каким именно образом Вы собираетесь регулировать амплитуду.
Я думаю, нужно выбрать какую то функцию, пробовал " float amp = volt;" , тоже не поучилось.
Величина "volt" меняется, может быть 1 вольт или 2 , напряжение подается на пин PA7.
Aмплитуда зависит от строчки # 18, могу менять 35 на другие числа и амплитуда меняется .
Амплитуду генератора программно изменить нельзя.
Вот вторая программа где амплитуду можна менять кнопками.
как заменить кнопки вольтметром ?
Напряжением на PA7. Строчка # 99 .
А что не работает то? Измеряемая амплитуда не соответствует задаваемой? Или совсем не мерется?
Первый код, амплитуда не меняется, измерение правильное.
После изменения amp надо вызвать initwave().
Какие строчки ?
В первом скече нет строк amp= в цикле loop, это если менять в процессе работы.
20 - лишняя.
19 - восстановить.
87 перенести после 91.
gal, да, в сообщении №6 амплитуда должна изменяться. Правда, сделано это неправильно, поэтому работать будет кое-как. Я, собственно, и задавал вопрос в сообщении №2, чтобы понять, стоит ли Вам предлагать этот вариант. Это - единственное, что можно сделать сравнительно небольшими изменениями. Чтобы сделать правильно, код нужно переписывать полностью.
Если Вас интересует, как сделать правильно, основную идею могу изложить. Но претворять ее в программный кодв Вам придется самому: я делал это только на ПК, на ARM есть своя специфика, в которой я не разбирался.
Если же Вас в принципе устраивает как работает то, что нарисовано в сообщении №6, то могу посоветовать, как это можно немного улучшить.
Реагирует на изменение напряжения на PА7, но синусоида превратилась в прямоугольник , нада гдето уменьшить амплитуду.
поменял "int amp = 5;", есть синусоида, но коротко 2 сек, а потом обратно самостоятельно в прямоугольник меняется .
gal, как Вы думаете, сколько времени понадобится мартышке, беспорядочно стучащей по клавишам, чтобы напечатать, пусть даже не "Войну и мир", но хотя бы "Капитанскую дочку"?
andriano
Спасибо за предложение улучшения работы кнопок, к этому вернусь, но сейчас программа почти работает и хочю её исправить.
Проблема связана с ЛСД, он включается с опозданием, пока он не включен синусоида есть.
Да какая разница, кнопки или не кнопки - суть от этого не меняется.
Ваш код из сообщения №0 не предназначен для оперативного изменения амплитуды.
Правильное решение - переписать код полностью.
Существует еще и неправильное, но кое-как работающее решение - дополнить код костылями.
Пример костылей содержится в сообщении №6.
А кнопкой Вы меняете амплитуду, энкодером, фотодатчиком или амплитудой внешнего сигнала - это несущественно.
Вольтметр показывает значение в милливольтах, надо поменять на вольты и должно быть хорошо.
В прямоугольники превращается, потому что есть положительная обратная связь. Вольты и амплитуда связаны не прямо. Строка 91 должна выглядеть как amp=k*volt; . float k надо подобрать что бы синус был нужной амплитуды. Может даже по условию чуть чуть менять amp если volt больше или меньше забанного.
Поставил " amp=0.78*volt;" - амплитуды выглядят одинаково.
andriano
Готовый делать изменения в посте в # 6
Нет, я вообще не рассматриваю этот вопрос.
Насколько я понял, Вы хотите переделать скетч №0 так, чтобы амплитуда сигнала зависела от некоторого внешнего сигнала. Строго говоря, скетч №0 не предназначен для изменения амплитуды в процессе работы. Чтобы сделать хорошо, его надо переписывать с 0. Но можно внести в скетч №0 заплатку, что он будет удовлетворять Вашему желанию, но при этом будет работать не очень хорошо. В смысле, в генерируемом им сигнале будут помехи. Величину их прогнозировать не берусь. Собственно, способ, как реализовать эту заплатку, Вы сами разместили в скетче №6. Но, повторяю, это не очень хороший способ.
Далее: если Вас полностью устраивает, как работает скетч №0, с внесенными в него изменениями из №6, то вопрос решен (т.е. Вы помехи почти не замечаете, либо их уровень не вызывает у Вас дискомфорта).
Если уровень помех таков, что кое-как мириться с ним можно, но хотелось бы его несколько снизить - в этом случе могу дать несколько советов, как это сделать.
Если уровень помех неприемлем, то, скорее всего, те поправки к заплатке, которые я могу предложить, не приведут к желаемому и, чтобы добиться хорошего результата, скетч придется переписывать с 0. Я могу высказать общую идею, что надо делать, но не смогу подсказать конкретную реализацию, т.к. повторяю, на ARM я этого не делал.
PS. И еще у меня впечатление, что те скетчи, что Вы размещаете, на само деле есть фрагменты более крурпного скетча, из которого Вы выбрасываете некоторые куски (не всегда удачно).
Да помехи пригодилось бы уменьшить. Подскажите что делать может мне получиться.
Многие AVR программы с Ардуино Уно работают в ARM
Да помехи пригодилось бы уменьшить. Подскажите что делать может мне получиться.
1. Чем длиннее буфера, тем меньше вероятность конфликта, когда DMAC и CPU пытаются обратиться к одной и той же ячейке. Поэтому желательно увеличить размер буфера. Благо, в Due памяти в 48 раз больше, чем в Uno.
2. На ARM, так же, как и на AVR нет FPU. Соответственно, плавающая точка считается крайне медленно. Поэтому целесообразно использовать такой алгоритм:
- заранее просчитать массив значений синуса в целых числах и внести его прямо в скетч с квалификатором const,
- когда потребуется перезаписать буфер DMAC, просто отмасштабировать заранее насчитанный массив в буфер с использованием только двух целочисленных операций - умножения и деления на степень двойки (возможно, еще сложения).
Многие AVR программы с Ардуино Уно работают в ARM
А это как?
[/quote]
А это как?
[/quote]
Часто хватает поменять название пинов, А0 на P А6 ......
Имеешь в виду Sine Look Up Table ?
http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml
В - функцию синуса - val1[i] = 50 + amp * sin(stp * i); ?
Имеешь в виду Sine Look Up Table ?
http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml
Честно говоря, вижу это в первый раз, поэтому иметь в виду никак не мог. Но если это самое простое для Вас решение - почему бы и нет. Только следует помнить, что синус здесь присутствует со смещением.
В - функцию синуса - val1[i] = 50 + amp * sin(stp * i); ?
Совершенно не понял ничего из того, что Вы написали.
Если Вы хотите генерировать синус тем способом, что в первом исходнике, то это совершенно невозможно. Да, и, кстати, управлять там амплитудой сигнала тоже совершенно невозможно.
Возвращаемся к сообщению 29 и 30
gal, похоже, Вы не умеете разговаривать иначе, кроме как загадками.
Свои предложения я изложил в сообщении №31.
Сейчас понял, ожидал каких то примеров.
С размещением примеров Вы и сами прекрасно справляетесь.
Когда буду прекрасно разбираться не буду спрашивать а отвечать.
Вообще-то можно сделать несколькими разными способами. Все зависит от того, чего именно Вы хотите этим добиться.
Можно и так, как Вы написали в сообщении №43.
Спасибо, завтра проверю.