На STM32, даже на f10x простой и сложный и с блэкждеком и шлюхами - ногодрыг делается на аппаратном уровне. Просто задержки скидываешь в массив и грузишь массив по ДМА в таймер, Точность - сам понимаешь - 1/72 мкс= 14 нс. Гы! Сейчас "ssss" как выпрыгнет! ;) ;) ;) ;) и покажет вам Кузькину мать!
Проклятье! Он вызвал этого вонючего демона :( Тему можна удалять.
ПС. "нужна регулировка длительности импульса" - для накачки высоковольтного конденсатора совсем не обязательно, вполне частотно-импульсной модуляции хватает. Хотя пути неисповедимы ))
Но ЗАРАНЕЕ пишу, что если тебе нужна регулировка длительности импульса в рантайме, то писать нужно немного не так. Тоже все спокойно делается с точностью до 62,5 нс и начиная от 125 нс, но писать сложнее, там выравнивать нужно будет по вариантам. Код не будет сильно изящьным, но можно спокойно обойтись только С, без Асма.
Этот вариант написать?
Канечна! Это и будет ответом на вопрос топика: "есть решение?" :)
Ещё раз, требуется ногодрыг с рантайм регулировкой (через переменную) длительности импульса кратно 250нсек, начиная от 250нсек. То есть: 250, 500, 750 .. а не 312.5, 562.5 и т.д.
Скажем так:
#define MAX_ADCS 2
#define MAX_SAMPLES 10
int adcs[MAX_ADCS*MAX_SAMPLES];
int * adcPtr;
for(int wait=1; wait<100; wait++){
adcPtr = adcs;
for(int i=0; i<MAX_SAMPLES; i++){
cli();
pwmOn();
delay250us(wait); // функция задержки кратно 250мксек как чтобы строго 250*wait?
pwmOf();
adcReadFast( adcPtr++ );
adcReadFast( adcPtr++ );
sei();
}
// тут скажем "вывод на плоттер" того что получилось в adcs ..
}
Примерчики с константами у меня и работали всю жизнь .. загляни ещё в старый arhat.h оно там так и прописано.
Проклятье! Он вызвал этого вонючего демона :( Тему можна удалять.
ПС. "нужна регулировка длительности импульса" - для накачки высоковольтного конденсатора совсем не обязательно, вполне частотно-импульсной модуляции хватает. Хотя пути неисповедимы ))
Уже и сделано через таймер и прерывания .. вопрос уже чисто академический про контролируемый ногодрыг.
Так нужен батл! Дед & gcc! На большем проекте. В трех номинациях, скорость компиляции, обем кода и скорость исполнения. Применение стимуляторов с обеих сторон приветствуется.
Уже и сделано через таймер и прерывания .. вопрос уже чисто академический про контролируемый ногодрыг.
Полез к се в код, глянул как делал. Предельно просто.
void loop()
{
int V=analogRead(A1);
int t=micros();
......
if(t-PulseT>700)
{
if(V<VALUE_ADC(Vhigh_))
{
PulseT=t;
digitalWrite(PIN_DRV, HIGH);_delay_us(20);digitalWrite(PIN_DRV, LOW);
}
}
если от прошлого импульса прошло более 700мксек, а напряжение ниже порога - импульс 20мксек. Даже прерывания не запретил, всех делов))) Лоп предельно быстрый, других делеев кроме этого нет. Статистика напряжения на датчике - Vmin=337V; Vmax=391V; Vs=353V; Вполне нормас. А импульс понятно по прерыванию, на таймере 1 время нечувствительности после импульса.
Логик! 20мксек - это задержка в моих wait = 80 (по 250нсек). Меня интересовало поведение при ширине импульса накачки до 1-2мксек, ваще-то с целью понять можно ли регулировать напряжение на выходе шириной импульса накачки, ибо не известно "скока вешать в граммах" для самодельной трубки Гейгера из шприца. То-ли 300-400 вольт толи под пару киловольт, как показывает оценка. :)
И тут как раз "чем мельче шаг" - тем толще партизаны. С таймером вполне получается шагать по 62.5нсек.
P.S. В общем, это я - тормоз. Ответ №1 и пост №2 содержат решение с самого начала. :)
6f8 - перенос из регистра в регистр, ибо переменная = 1 такт. 6fa - декремент = 2 такта, 6fc - сравнение .. и вот тут я подзабыл: переход выполняется 2 такта, если "НЕ РАВНО НУЛЮ" (взад, повтор цикла) и ОДИН ТАКТ если "равно нулю" .. итого имеем 4 такта при мин. задержке "1". Соответственно, все тут как надо: 250, 500, ..
Логик! 20мксек - это задержка в моих wait = 80 (по 250нсек). Меня интересовало поведение при ширине импульса накачки до 1-2мксек
Пробовал я на 1-2мксек работать. С заводским датчиком. Не получалось выйти на нужные напряжения. Но я больше не о том говорю. В данном случае ШИМ не нужен, ИМХО. Самое оно - фиксированая, экспериментально найденая длительность импульса, а стабилизация напряжения за счет изменения паузы между импульсами. То, что на таймере шаг 62.5нсек получить можно никто наверно и не сомневался. А для самопального датчика думаю обязательно надо "плато" искать. От него собственно все и пляшет. Минимальное напряжение задает порог при проседании до которого пора делать импульс, а длительность импульса определяется разностю максимального и минимального. Если длительность делать больше, то превысим максимальное. По таким соображениям и цифра 20мксек вышла.
В общем-то получил похожие результаты, что огорчило и сильно. Плато - надо искать, а перестраиваемый ВВ блок накачки сделать на той схеме - шибко сомнительно. Потому что да, у каждого такого транса есть своя оптимальная длительность импульса и накачивает он ровно до своего "передаточного отношения".
Знать бы в каком диапазоне напряжений его искать, это "плато"..
P.S. По теме:
Как итого, перетасовки кода имеют место быть, управляются опциями они достаточно слабо и каждый ногодрыг надо смотреть в ассемблере чего туда натыкает оптимизатор. Или критические по исполнению последовательности оформлять asm() вставками с атрибутом volatile. Или устанавливать атрибутно опции оптимизатору на конкретно эту функцию, но тогда код придется заворачивать в функцию, ибо установка атрибутики на блок кода {..} не нашел "как".
P.P.S. Тема получилась забавная, может кому будет полезна, особенно писателям "библиотек" с ногодрыгами.
... перименовал тему. Ежели кто чего найдет ишо, можно будет дополнять вопрос. Если возражений по выводу предыдущего поста нет, то перенесу его в первый пост как "краткий вывод по теме для тех кому лень листать топик".
Ещё раз, требуется ногодрыг с рантайм регулировкой (через переменную) длительности импульса кратно 250нсек, начиная от 250нсек. То есть: 250, 500, 750 .. а не 312.5, 562.5 и т.д.
Arhat109-2 пишет:
Спасибо конечно за труд, но Вы решили ИНУЮ задачу .. :) Решение того что было надо содержится в посте №2, на самом деле работает как надо.
я стесняюсь спросить, как в твоей башне склеиваются эти две цитаты? Принимая во внимание тайминги?
Хотя твое дело... Компилятор все равно во всем виновотым окажется... ну и я , до кучи.
/**
* Тест накачки высокого обратноходовым импульсным преобразователем
* В этом варианте показывает до 679 попугаев или 1384в на ВВ-трансфоматоре (№1)
* Делитель 100мОм + 240кОм: = 100.24 / 0,24 * (5в/1024) = 2,04 вольта на 1 попугай АЦП.
* при импульсе длительностью от 8.25 до 10.25 мксек.
*
* АЦП НАНО: 4Мгц - 5бит, 2Мгц - 6-7бит, 1Мгц - 8бит.
* АЦП МУРК-2560: 8Мгц - 5..6бит, 4Мгц - 6..7бит, 2Мгц - 7..8бит, 1Мгц - >8бит.
* все кривые младшие значения результата обнулены! (ошибку можно располовинить)
* Время замера строго 13.5тактов АЦП. Не забывать про последний "запуск" в adcReadFast()!
* МУРК-2560: AREF - 100нф, AVCC - (20мкГн + 2х4.7мкф)
*/
#define pinPWM 5 /* PORTD PORTD5*/
#define pinHV 0 /* analog pin A0! */
#define MAX_ADCS 4
#define MAX_SAMPLES 10
int adcs[MAX_ADCS*MAX_SAMPLES];
#define pwmON() (PORTD |= 0B00100000)
#define pwmOFF() (PORTD &= 0B11011111)
/**
* INLINE: 16-bit counter: up to 65535*4 F_CPU for 16Mhz:[0.25 .. 16383.75] mcsec.
* Короткие задержки по 4 цикла ЦПУ (кратно 250 нсек)
*/
#define delayMicro16(__count) \
__asm__ __volatile__ ( \
"1: sbiw %0,1 \n\t" \
"brne 1b\n\t" \
: "=w" (__count) \
: "0" (__count) \
)
#define adcStart() (ADCSRA |= (1<<ADSC))
#define adcWait() while(ADCSRA&(1<<ADSC))
/**
* Однократное чтение АЦП 8-бит (младших)
* Если замер завершен, то сначала запуск следующего. Пока идет замер - работаем дальше
*/
#define adcReadFast(res) \
{ \
adcWait(); \
adcStart(); \
(res)=ADC; \
}
void setup()
{
pinMode(pinPWM, OUTPUT);
pwmOFF();
Serial.begin(115200);
ADCSRA = (1<<ADEN) | (2); // включаем АЦП и устанавливаем делитель 1(8), 2(4), 3(2), 4(1), 5(0.5), 6(0.25), 7(0.125)
ADMUX = (0<<REFS1)|(1<<REFS0)|(pinHV); // 01 - опорное 5в, рабочий вход - pinHV
ADCSRB = 0; // тут ничего не надо
DIDR0 = 255; // отключаем от OUTPUT все входы АЦП, дабы не разбираться
adcStart(); // запуск и сразу
adcWait(); // пропуск первого чтения, ибо мусор и долго
}
void loop()
{
int *ptr;
for(int wait=1; wait<100; wait++){
ptr = adcs;
for(uint8_t n=0; n<MAX_SAMPLES; n++){
int _w = wait;
cli();
pwmON();
delayMicro16(_w);
pwmOFF();
adcStart();
adcReadFast(*ptr++); // MAX_ADCS раз!
adcReadFast(*ptr++);
adcReadFast(*ptr++);
adcReadFast(*ptr++);
adcWait(); // пропуск последнего запуска АЦП
sei();
}
// вывод попыток накачки на плоттер
for(uint8_t n=0; n<MAX_SAMPLES; n++){
for(uint8_t i=0; i<5; i++){ Serial.println(n, DEC); }
for(uint8_t i=0; i<MAX_ADCS; i++){
Serial.println( adcs[i+n*MAX_ADCS], DEC);
}
}
}
delay(2000); // пауза для просмотра результатов
}
Это код теста, как оно и предполагалось, переменная wait - есть счетчик цикла по размеру задержки. Вывод на плоттер по 10 импульсов накачки на посмотреть докудова докачивает измерялкой на АЦП. Измерялка сделана как можно шустрее, задержка промеж импульсов накачки регулировалась как количеством чтений АЦП, так и изменением частоты оцифровки. Тут стоит макс. в 4Мгц, поскольку гонялось на НАНО, а она 8Мгц не тянет.
Результат компиляции блока ногодрыга на ИДЕ 1.6.9.:
В звездочках - тайминг операций согласно AVR-ASM. Итого, цикл задержки: 1+2+4*(wait-1)+1 .. строго кратно 250нсек, начиная с самой первой задержки.
Забавно то, что в коде необходимость оператора int _w = wait; обязательна, но в итоге оно оказывается редуцировано оптимизатором. Операция строки 138 - неустранима, ибо параметр макроса в асм-вставке указан как "возвращаемая переменная".
То, что писал про "константу" Евгению: это - тестовый код, в котором длительность wait - подбирается под оптимум. В окончательном коде ожидалось применение delayMicro16(4), с указанием конкретно подобранной константы. Однако ТАК с этим вариантом макроса - не получится, будет сгенерена ошибка: "Lvalue required", что верно.
Как видно, никаких специальных опций компилятору указывать не пришлось вовсе. :)
Ох! Не смог удержаться! ;) ;) ;)
=====НИЖЕ ЧИСТЫЙ ТРОЛЛИНГ================
На STM32, даже на f10x простой и сложный и с блэкждеком и шлюхами - ногодрыг делается на аппаратном уровне. Просто задержки скидываешь в массив и грузишь массив по ДМА в таймер, Точность - сам понимаешь - 1/72 мкс= 14 нс. Гы! Сейчас "ssss" как выпрыгнет! ;) ;) ;) ;) и покажет вам Кузькину мать!
=================================
Приношу извинения за троллинг ув. "All"!
Проклятье! Он вызвал этого вонючего демона :( Тему можна удалять.
ПС. "нужна регулировка длительности импульса" - для накачки высоковольтного конденсатора совсем не обязательно, вполне частотно-импульсной модуляции хватает. Хотя пути неисповедимы ))
Этот вариант написать?
Канечна! Это и будет ответом на вопрос топика: "есть решение?" :)
Ещё раз, требуется ногодрыг с рантайм регулировкой (через переменную) длительности импульса кратно 250нсек, начиная от 250нсек. То есть: 250, 500, 750 .. а не 312.5, 562.5 и т.д.
Скажем так:
Примерчики с константами у меня и работали всю жизнь .. загляни ещё в старый arhat.h оно там так и прописано.
Проклятье! Он вызвал этого вонючего демона :( Тему можна удалять.
ПС. "нужна регулировка длительности импульса" - для накачки высоковольтного конденсатора совсем не обязательно, вполне частотно-импульсной модуляции хватает. Хотя пути неисповедимы ))
Уже и сделано через таймер и прерывания .. вопрос уже чисто академический про контролируемый ногодрыг.
вот не зря я забивал на С и компилятор, в машинных кодах всё проще )))
да. этот ваш лжывый с++ даже мне в оптимизацеи проигрывает. даже, када я - бухой.
да. этот ваш лжывый с++ даже мне в оптимизацеи проигрывает. даже, када я - бухой.
А так нещитова! Вас ваще дисквалифицировать за доппинг надоть!
Так нужен батл! Дед & gcc! На большем проекте. В трех номинациях, скорость компиляции, обем кода и скорость исполнения. Применение стимуляторов с обеих сторон приветствуется.
Уже и сделано через таймер и прерывания .. вопрос уже чисто академический про контролируемый ногодрыг.
Полез к се в код, глянул как делал. Предельно просто.
если от прошлого импульса прошло более 700мксек, а напряжение ниже порога - импульс 20мксек. Даже прерывания не запретил, всех делов))) Лоп предельно быстрый, других делеев кроме этого нет. Статистика напряжения на датчике - Vmin=337V; Vmax=391V; Vs=353V; Вполне нормас. А импульс понятно по прерыванию, на таймере 1 время нечувствительности после импульса.
Логик! 20мксек - это задержка в моих wait = 80 (по 250нсек). Меня интересовало поведение при ширине импульса накачки до 1-2мксек, ваще-то с целью понять можно ли регулировать напряжение на выходе шириной импульса накачки, ибо не известно "скока вешать в граммах" для самодельной трубки Гейгера из шприца. То-ли 300-400 вольт толи под пару киловольт, как показывает оценка. :)
И тут как раз "чем мельче шаг" - тем толще партизаны. С таймером вполне получается шагать по 62.5нсек.
P.S. В общем, это я - тормоз. Ответ №1 и пост №2 содержат решение с самого начала. :)
6f8 - перенос из регистра в регистр, ибо переменная = 1 такт. 6fa - декремент = 2 такта, 6fc - сравнение .. и вот тут я подзабыл: переход выполняется 2 такта, если "НЕ РАВНО НУЛЮ" (взад, повтор цикла) и ОДИН ТАКТ если "равно нулю" .. итого имеем 4 такта при мин. задержке "1". Соответственно, все тут как надо: 250, 500, ..
:)
прости, брат, но ты это чисто аналитически считаешь, без логаналайзера? отползаю....
сорри, я что обещал утром... моим, московским, т.е. часв в 12 по мск. завтра напишу.... щаз я уже бухой
Логик! 20мксек - это задержка в моих wait = 80 (по 250нсек). Меня интересовало поведение при ширине импульса накачки до 1-2мксек
Пробовал я на 1-2мксек работать. С заводским датчиком. Не получалось выйти на нужные напряжения. Но я больше не о том говорю. В данном случае ШИМ не нужен, ИМХО. Самое оно - фиксированая, экспериментально найденая длительность импульса, а стабилизация напряжения за счет изменения паузы между импульсами. То, что на таймере шаг 62.5нсек получить можно никто наверно и не сомневался. А для самопального датчика думаю обязательно надо "плато" искать. От него собственно все и пляшет. Минимальное напряжение задает порог при проседании до которого пора делать импульс, а длительность импульса определяется разностю максимального и минимального. Если длительность делать больше, то превысим максимальное. По таким соображениям и цифра 20мксек вышла.
В общем-то получил похожие результаты, что огорчило и сильно. Плато - надо искать, а перестраиваемый ВВ блок накачки сделать на той схеме - шибко сомнительно. Потому что да, у каждого такого транса есть своя оптимальная длительность импульса и накачивает он ровно до своего "передаточного отношения".
Знать бы в каком диапазоне напряжений его искать, это "плато"..
P.S. По теме:
Как итого, перетасовки кода имеют место быть, управляются опциями они достаточно слабо и каждый ногодрыг надо смотреть в ассемблере чего туда натыкает оптимизатор. Или критические по исполнению последовательности оформлять asm() вставками с атрибутом volatile. Или устанавливать атрибутно опции оптимизатору на конкретно эту функцию, но тогда код придется заворачивать в функцию, ибо установка атрибутики на блок кода {..} не нашел "как".
P.P.S. Тема получилась забавная, может кому будет полезна, особенно писателям "библиотек" с ногодрыгами.
... перименовал тему. Ежели кто чего найдет ишо, можно будет дополнять вопрос. Если возражений по выводу предыдущего поста нет, то перенесу его в первый пост как "краткий вывод по теме для тех кому лень листать топик".
ФИгню, как обычно написал - на блок кода постевить опции нельзя, #pragma тоже работает на единицы компиляции.
============
То, что вчера обещал, обкатал на логаналайзере.
Тайминги:
Спасибо конечно за труд, но Вы решили ИНУЮ задачу .. :) Решение того что было надо содержится в посте №2, на самом деле работает как надо.
Спасибо конечно за труд, но Вы решили ИНУЮ задачу .. :) Решение того что было надо содержится в посте №2, на самом деле работает как надо.
а тайминги можно показать?
Ещё раз, требуется ногодрыг с рантайм регулировкой (через переменную) длительности импульса кратно 250нсек, начиная от 250нсек. То есть: 250, 500, 750 .. а не 312.5, 562.5 и т.д.
Спасибо конечно за труд, но Вы решили ИНУЮ задачу .. :) Решение того что было надо содержится в посте №2, на самом деле работает как надо.
я стесняюсь спросить, как в твоей башне склеиваются эти две цитаты? Принимая во внимание тайминги?
Хотя твое дело... Компилятор все равно во всем виновотым окажется... ну и я , до кучи.
Ну только вот так:
Это код теста, как оно и предполагалось, переменная wait - есть счетчик цикла по размеру задержки. Вывод на плоттер по 10 импульсов накачки на посмотреть докудова докачивает измерялкой на АЦП. Измерялка сделана как можно шустрее, задержка промеж импульсов накачки регулировалась как количеством чтений АЦП, так и изменением частоты оцифровки. Тут стоит макс. в 4Мгц, поскольку гонялось на НАНО, а она 8Мгц не тянет.
Результат компиляции блока ногодрыга на ИДЕ 1.6.9.:
В звездочках - тайминг операций согласно AVR-ASM. Итого, цикл задержки: 1+2+4*(wait-1)+1 .. строго кратно 250нсек, начиная с самой первой задержки.
Забавно то, что в коде необходимость оператора int _w = wait; обязательна, но в итоге оно оказывается редуцировано оптимизатором. Операция строки 138 - неустранима, ибо параметр макроса в асм-вставке указан как "возвращаемая переменная".
То, что писал про "константу" Евгению: это - тестовый код, в котором длительность wait - подбирается под оптимум. В окончательном коде ожидалось применение delayMicro16(4), с указанием конкретно подобранной константы. Однако ТАК с этим вариантом макроса - не получится, будет сгенерена ошибка: "Lvalue required", что верно.
Как видно, никаких специальных опций компилятору указывать не пришлось вовсе. :)