Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
0 / 0 / 0
Регистрация: 01.03.2017
Сообщений: 27

Оптимизация для повышения частоты ШИМ

29.10.2020, 20:37. Показов 3216. Ответов 36

Студворк — интернет-сервис помощи студентам
Добрый день. Пишу программу для многоканального ШИМ-контроллера на основе Attiny13. Так как у него всего два аппаратных канала, использую программное управление в прерывании таймера.
Сначала планировалось ШИМить с низкой частотой (10 Гц), но шумовые эффекты все равно значительны. А вот с поднятием частоты до 20 кГц возникли затруднения.

Сначала было так (обработчик прерывания). Такой код выполнялся 54 такта и при тактовой 9.6 МГц и разрешении ШИМ 16 уровней давал менее 10 кГц на выходах.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Прерывание по совпадению счетчика
// Выходные каналы - PB0, PB1, PB2 и PB3
// Уставки ШИМ - pwm1...pwm4
ISR(TIM0_COMPA_vect)
{
    if(cnt<pwm1) PORTB |= (1<<0);
    else PORTB &= ~(1<<0);
    if(cnt<pwm2) PORTB |= (1<<1);
    else PORTB &= ~(1<<1);
    if(cnt<pwm3) PORTB |= (1<<2);
    else PORTB &= ~(1<<2);
    if(cnt<pwm4) PORTB |= (1<<3);
    else PORTB &= ~(1<<3);
    cnt++;
}
Пораскинул мозгами, перенёс этот код в главный цикл, формировать массив с 16 значениями на 16 моментов времени.
Обработчик уменьшился, теперь 30 тактов, однако оказалось, что из-за накладных расходов едва ли дотянулось до 10 кГц.
C
1
2
3
4
5
ISR(TIM0_COMPA_vect)
{
    PORTB = port_out_table[cnt];
    cnt == PWM_RES ? cnt = 0 : cnt++;
}
Глянул ассемблерный листинг, а там куча "лишних" операций, в основном освобождение необходимых регистров:
Кликните здесь для просмотра всего текста
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
00000019  PUSH R1       Push register on stack 
0000001A  PUSH R0       Push register on stack 
0000001B  IN R0,0x3F        In from I/O location 
0000001C  PUSH R0       Push register on stack 
0000001D  CLR R1        Clear Register 
--- C:\Users\Pa-vm-10\Documents\Atmel Studio\7.0\t13fan-control\t13fan-control\Debug/.././main.c 
0000001E  PUSH R24      Push register on stack 
0000001F  PUSH R30      Push register on stack 
00000020  PUSH R31      Push register on stack 
    PORTB = port_out_table[cnt];
00000021  LDS R30,0x0062        Load direct from data space 
00000023  LDI R31,0x00      Load immediate 
00000024  SUBI R30,0x7F     Subtract immediate 
00000025  SBCI R31,0xFF     Subtract immediate with carry 
00000026  LDD R24,Z+0       Load indirect with displacement 
00000027  OUT 0x18,R24      Out to I/O location 
    cnt == PWM_RES ? cnt = 0 : cnt++;
00000028  LDS R24,0x0062        Load direct from data space 
0000002A  CPI R24,0x0F      Compare with immediate 
0000002B  BRNE PC+0x04      Branch if not equal 
--- No source file -------------------------------------------------------------
0000002C  STS 0x0062,R1     Store direct to data space 
0000002E  RJMP PC+0x0004        Relative jump 
0000002F  SUBI R24,0xFF     Subtract immediate 
00000030  STS 0x0062,R24        Store direct to data space 
00000032  POP R31       Pop register from stack 
00000033  POP R30       Pop register from stack 
00000034  POP R24       Pop register from stack 
00000035  POP R0        Pop register from stack 
00000036  OUT 0x3F,R0       Out to I/O location 
00000037  POP R0        Pop register from stack 
00000038  POP R1        Pop register from stack 
00000039  RETI      Interrupt return


Я более-менее имею опыт в ассемблере, но переписывать весь код в нём не хочется, остальная часть проги (юарт, проверка настроек, контроль температур) написана и отлажена. Что можно сделать конкретно в этом обработчике, не представляю. Как-то перенести часть операций в медленную часть, что-ли.
Есть отчаянные варианты, например забить в OSCCAL максимальное значение, но тогда может пострадать чтение и запись еепром. Или внешний ТГ на 20 МГц, но ножек не хватит.
Переделать аппаратную часть, вроде фильтра на выход, это самое сложное решение, как обычно. Аппарат... немножко неразборный, и проще сделать новый с нуля.

Буду благодарен за любые намёки, наводки и прочее.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.10.2020, 20:37
Ответы с готовыми решениями:

регулирование частоты шим
сабж, помогите. не пойму как у atmega регулируется частота шим.

Реализация плавного повышения частоты пьезоизлучателя.
Добрый вечер. Неполучается написать программу на С для atmega8, которая бы при удержании кнопки плавно повышала бы частоту колебаний на...

Изменение частоты/скважности ШИМ
Здравствуйте, уважаемые участники форума. Возник момент: хочу регулировать частоту ШИМ на Микроконтроллере STM32 (плата f407G1 discovery,...

36
Тутошний я
 Аватар для Grey
2147 / 1202 / 225
Регистрация: 03.11.2009
Сообщений: 4,424
Записей в блоге: 2
30.10.2020, 23:16
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от ValeryS Посмотреть сообщение
ниче разбросы или 10 Герц или 20 килоГерц
я так подумал. видимо индуктивности двигателя не хватает чтоб сгладить импульсы. и сам двигатель на этой частоте гудит.
а 10 Герц или 20 килоГерц за пределами слышимости.
тогда только один вариант. переходить на stm.
0
0 / 0 / 0
Регистрация: 01.03.2017
Сообщений: 27
30.10.2020, 23:37  [ТС]
Цитата Сообщение от ValeryS Посмотреть сообщение
а шум вентиляторов не учитываешь?
Не экономлю на вертушках, хорошие вентиляторы (не обязательно дорогие) даже на полной скорости не громче пары НЖМД. Частоту ШИМа разную пробовал, вентиляторы прекрасно пищат даже на 15 кГц, что рядом сидеть невозможно. Но, это если в них нет конденсатора по входу. А если он есть, то нужны и транзисторы помощнее, и линейность управления теряется.
Цитата Сообщение от Kukuxumushu Посмотреть сообщение
Я вам уже советовал портироваться на CVAVR.
Спасибо, обязательно попробую.

Добавлено через 1 минуту
Цитата Сообщение от Grey Посмотреть сообщение
видимо индуктивности двигателя не хватает чтоб сгладить импульсы.
Да какой сгладить. В моей практике видел и пищащие индуктивности, залитые в компаунд, и читал про пищащие дорожки на плате, а в вентиляторе обмотки на воздухе висят и вольны вибрировать как угодно.
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,876
30.10.2020, 23:54
Цитата Сообщение от Grey Посмотреть сообщение
а 10 Герц или 20 килоГерц за пределами слышимости.
откуда сие известно?
диапазон слышимости среднестатистического человека 20-20000 Гц, но есть люди которые слышат и 21000 и 16
Цитата Сообщение от Grey Посмотреть сообщение
видимо индуктивности двигателя не хватает чтоб сгладить импульсы.
кроме индуктивности катушки есть и ,так назовем, "механическая индуктивность"-масса ротора и масса крыльчатки
и боюсь что потери на 20000 Гц в катушке будут достаточно большими КПД упадет

Добавлено через 2 минуты
Цитата Сообщение от pusyakaryagin Посмотреть сообщение
Не экономлю на вертушках, хорошие вентиляторы
даже если идеальные вентиляторы, они все равно рассекают воздух, закручивают его, вот он и свистит
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
31.10.2020, 00:13
Цитата Сообщение от pusyakaryagin Посмотреть сообщение
я не смог объявить глобальную переменную-регистр
что, и вариант из GCC-мануалов тоже не работает? (https://gcc.gnu.org/onlinedocs... les.html):
C
1
register int *foo asm ("r12");
Цитата Сообщение от Kukuxumushu Посмотреть сообщение
Там это дело реализуется директивой #pragma savereg off перед шапкой прерывания
никогда не использовал (имеется ввиду, эту директиву в CVAVR), но интересно. Спасибо за наводку, наверное, может и пригодиться в простых задачках ).
PS: вот только для прерываний я не могу пока понять - зачем это может понадобиться? Ведь хранение переменных в прерываниях - это основа. Иначе просто непонятно, как программа сможет работать с прерываниями, ничего не храня в регистрах.
1
Тутошний я
 Аватар для Grey
2147 / 1202 / 225
Регистрация: 03.11.2009
Сообщений: 4,424
Записей в блоге: 2
31.10.2020, 01:39
Цитата Сообщение от ValeryS Посмотреть сообщение
"механическая индуктивность"-масса ротора и масса крыльчатки

а в этом ещё интересней. сам моторчик пищит. на 4:40.
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,876
31.10.2020, 07:24
Grey, как думаешь, между переменным и импульсным напряжением есть разница?
0
658 / 411 / 76
Регистрация: 21.09.2008
Сообщений: 1,411
31.10.2020, 09:59
Kukuxumushu, в разделе документации на AVR LibC указано, как можно сделать "голый" (без пролога и эпилога) обработчик прерывания.

Manually defined ISRs

In some circumstances, the compiler-generated prologue and epilogue of the ISR might not be optimal for the job,
and a manually defined ISR could be considered particularly to speedup the interrupt handling.
One solution to this could be to implement the entire ISR as manual assembly code in a separate (assembly) file.
See Combining C and assembly source files for an example of how to implement it that way.
Another solution is to still implement the ISR in C language but take over the compiler's job of generating the
prologue and epilogue. This can be done using the ISR_NAKED attribute to the ISR() macro. Note that the
compiler does not generate anything as prologue or epilogue, so the final reti() must be provided by the actual
implementation. SREG must be manually saved if the ISR code modifies it, and the compiler-implied assumption of
__zero_reg__ always being 0 could be wrong (e. g. when interrupting right after of a MUL instruction).
C
1
2
3
4
5
ISR(TIMER1_OVF_vect, ISR_NAKED)
{
PORTB |= _BV(0); // results in SBI which does not affect SREG
reti();
}
2
 Аватар для Kukuxumushu
1624 / 806 / 146
Регистрация: 13.06.2015
Сообщений: 3,266
31.10.2020, 10:15
Цитата Сообщение от Voland_ Посмотреть сообщение
Иначе просто непонятно, как программа сможет работать с прерываниями, ничего не храня в регистрах.
Для этого существует соглашение об использовании регистров. Некоторые из них компилятор никогда не трогает именно для таких случаев.
0
0 / 0 / 0
Регистрация: 01.03.2017
Сообщений: 27
31.10.2020, 18:26  [ТС]
Всем спасибо, особенно за ISR_NAKED и глобальную регистровую переменную.
Написал так, выполняется за 27 тактов, включая RETI и начальный RJMP из таблицы прерываний.
При вызове раз в 30 тактов частота вызова, умноженная на 16 отсчетов ШИМ, ровно 20 000 Гц.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
register uint8_t *cnt asm ("r16");
ISR(TIM0_COMPA_vect, ISR_NAKED)
// Timer interrupt handler
{   /*
     below code is equivalent of
      PORTB = port_out_table[*cnt];
      *cnt == PWM_RES ? *cnt = 0 : *cnt++;
      
      Input: counter "cnt" in r16, port_out_table[16] in 0x80 
     */
    asm volatile ( // 0x18 = portb
 
        "push r30"     "\n\t" // save ZL
        "in  r30,0x3f" "\n\t" // load SREG
        "push r30"     "\n\t" // save SREG
        "ldi r30,0x80" "\n\t" // load array addr 
        "add r30,r16"  "\n\t" // addr+=counter
        "ld r30,Z"     "\n\t" // read byte
        "out 0x18,r30" "\n\t" // byte to PORTB
        "inc r16"      "\n\t" // counter++
        "cpi r16,0x10" "\n\t" // counter == 16 ?
        "brne .+2"     "\n\t" // skip clr if not 16
        "clr r16"      "\n\t" // counter = 0    
        "pop r30"      "\n\t" // get SREG
        "out 0x3f,r30" "\n\t" // return SREG
        "pop r30"      "\n\t" // get ZL
        "reti"         "\n\t" // return from interrupt
        : 
        : 
    );
}
TODO: сделать подстановку адреса начала массива с таблицей, в данный момент он задан числом.
Если уговорить компилятор зарезервировать регистры 30 и 31, то прерывание можно освободить от первой и последней инструкции (минус 2 такта). Вероятно, это можно сделать опцией компиляции -ffixed-r30 даже в Атмел студио, но не пробовал.
В данном коде расчет на то, что в регистре ZH всегда ноль (должно быть справедливо для МК с маленькой памятью).
Если не жалко регистры, можно SREG класть не в стек, а в регистр, заранее зарезервированный. (минус 2 такта)
Ну и если во всём коде не используется умножение инструкцией, то таблицу с 16 значениями вариантов выхода можно вообще держать в регистрах (минус, вероятно, еще 3 такта)

(возможно, где-то я прав)
0
31.10.2020, 20:33

Не по теме:

Цитата Сообщение от ValeryS Посмотреть сообщение
Grey, как думаешь, между переменным и импульсным напряжением есть разница?
есть.
импульсное бывает произвольной формы и содержит много гармоник.
переменное имеет одну гармонику и симметрично относительно оси, нуля. если к переменному добавить постоянную составляющую получим импульсное напряжение.

0
31.10.2020, 23:56

Не по теме:

Цитата Сообщение от Grey Посмотреть сообщение
переменное имеет одну гармонику
меандр с уровнями +1 и -1 это переменное или импульсное?
но дело не в этом, а в
Цитата Сообщение от Grey Посмотреть сообщение
если к переменному добавить постоянную составляющую
на предоставленном тобой видео(1 ролик) на движок подается переменное напряжение ротор не вращается, точнее колеблется всегда около одной точки, было бы импульсное было бы вращение и при определенной частоте он бы не пел

0
Тутошний я
 Аватар для Grey
2147 / 1202 / 225
Регистрация: 03.11.2009
Сообщений: 4,424
Записей в блоге: 2
01.11.2020, 01:33

Не по теме:

в меандре много гармоник. это импульсное.

Цитата Сообщение от ValeryS Посмотреть сообщение
на предоставленном тобой видео(1 ролик) на движок подается переменное напряжение
в первом видео подаётся звуковой сигнал, имеющий много гармоник. можно сказать это импульсное напряжение. но точно не переменное.
Цитата Сообщение от ValeryS Посмотреть сообщение
"механическая индуктивность"-масса ротора и масса крыльчатки
индуктивность обмоток сглаживает сигнал.
"механическая индуктивность" сглаживает вращение.
Цитата Сообщение от Grey Посмотреть сообщение
видимо индуктивности двигателя не хватает чтоб сгладить импульсы. и сам двигатель на этой частоте гудит.
а видео ротора стоят, а двигатели шумят. я об этом.



Добавлено через 2 минуты
Цитата Сообщение от ValeryS Посмотреть сообщение
и при определенной частоте он бы не пел
ну насколько я понял, ТС и хочет поднять частоту выши порога слышимости.
0
01.11.2020, 09:30

Не по теме:

Цитата Сообщение от Grey Посмотреть сообщение
индуктивность обмоток сглаживает сигнал.
"механическая индуктивность" сглаживает вращение.
м выделяет постоянную составляющую, а от неё происходит вращение
ладно хватит офтопить, если есть желание давай создадим другую тему

0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
02.11.2020, 11:00
Цитата Сообщение от pusyakaryagin Посмотреть сообщение
где-то я прав
Цитата Сообщение от pusyakaryagin Посмотреть сообщение
Assembler
1
2
"cpi r16,0x10" "\n\t" // counter == 16 ?
        "brne .+2"     "\n\t" // skip clr if not 16
^^ вот это можно заменить на
Assembler
1
sbrc r16, 4
[если правильно помню]

Добавлено через 2 минуты
и в коде вы читаете по адресу регистра Z, но не гарантируете правильное значение ZH. Это опасно вообще-то

Добавлено через 18 минут
...почитал Ваши комменты к коду - многое Вы и без меня учли . Я бы порекомендовал использовать 16ти битный регистр и глобальную переменную с сохранением адреса. Это даст возможность читать и сравнивать немного (как мне навскидку кажется) быстрее. Вот так примерно:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
register uint16_t *addr asm ("r30");
uint8_t buf[16] __atribute__((aligned(32))); // To-check proper alignment
 
ISR(TIM0_COMPA_vect, ISR_NAKED)
// Timer interrupt handler
{   /*
     below code is equivalent of
      PORTB = port_out_table[*cnt];
      *cnt == PWM_RES ? *cnt = 0 : *cnt++;
      
      Input: counter "cnt" in r16, port_out_table[16] in 0x80 
     */
    asm volatile ( // 0x18 = portb
       "push r29"     "\n\t"
       "push r28"   "\n\t"
        "in  r29,0x3f" "\n\t" // load SREG
        "ld r28,Z"     "\n\t" // read byte
        "out 0x18,r28" "\n\t" // byte to PORTB
        "addiw r30, 1"      "\n\t" // counter++
        "sbic r31, 4" "\n\t" // [assume buffer address is 32byte aligned]
        "clr r31"      "\n\t" // counter = 0    
        "pop r30"      "\n\t" // get SREG
        "out 0x3f,r29" "\n\t" // return SREG
        "pop r28"      "\n\t"
        "pop r29"      "\n\t"
        "reti"         "\n\t" // return from interrupt
}
При старте надо присвоить
C
1
addr = (uint8_t*)buf;
1
0 / 0 / 0
Регистрация: 01.03.2017
Сообщений: 27
02.11.2020, 12:51  [ТС]
Цитата Сообщение от Voland_ Посмотреть сообщение
"cpi r16,0x10"
"brne .+2"
^^ вот это можно заменить на
sbrc r16, 4
Действительно, только это справедливо для круглых двоичных чисел. Мне тут пришлось 0х10 заменить на 0х0f, и это не прокатит. Зачем - ниже рассказываю.

Цитата Сообщение от Voland_ Посмотреть сообщение
в коде вы читаете по адресу регистра Z, но не гарантируете правильное значение ZH
Здесь ладно, память маленькая, но в общем случае стоит резервировать оба регистра Z и в инициализации их очищать, потому что часть ассемблерного кода подставляется, как я понимаю, из стандартного файла, и этот код, например, оставляет мусор в r16 и r17, а также 30 (там инициализация стека и что-то ещё).
А еще я беру ассемблерный код после компиляции и просто ищу в нём имена моих регистров, чтобы знать, где они задействованы. Да, -ffixed-rXX в атмел студии работает (помимо блока инициализации).

Цитата Сообщение от Voland_ Посмотреть сообщение
Assembler
1
2
3
4
5
 "ld r28,Z"     "\n\t" // read byte
 "out 0x18,r28" "\n\t" // byte to PORTB
 "addiw r30, 1" "\n\t" // counter++
 "sbic r31, 4"   "\n\t" // [assume buffer address is 32byte aligned]
 "clr r31"       "\n\t" // counter = 0
Тут немного не понял, что сравнивается в 4 инструкции, ведь r31 вроде как пуст. Еще отмечу, что ADIW занимает два такта.

Так вот, в моём алгоритме была неявная ошибка. У меня был массив из 16 байт на 16 временных позиций, или отсчетов, ШИМ. И прерывание вызывалось 16 раз, после чего начинало проходить массив сначала.
Такое решение не позволяет достичь 100% открытия канала, в максимуме он будет открыт на 15/16. Решения два: или увеличить массив значений до 17 байт, и заставить программу управления (которая на компе) давать значения ШИМ в диапазоне 0..16, или уменьшить число вызовов прерывания за период, чтобы отсчетов стало 15, и тогда будет доступно все 16 состояний (уровней). Это как 15 сосисок в цепочке, у которой 16 перехватов (включая крайние). Нельзя сделать и 16 сосисок, и 16 перехватов.
Сделал по второму, это к тому же подняло частоту до 21.3 кГц.

А вот как я получил адрес начала массива, и записал его в регистр:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*  Глобально  */
register uint8_t *addr asm("r4");
 
/* В обработчике прерывания: */
asm volatile ( // 0x18 = portb
 
        "in  r10,0x3f" "\n\t" // load SREG
        "mov r30,r4" "\n\t" // load array addr 
        "add r30,r16"  "\n\t" // addr+=counter
        "ld r30,Z"     "\n\t" // read byte
        "out 0x18,r30" "\n\t" // byte to PORTB
        "inc r16"      "\n\t" // counter++
        "cpi r16,0xf" "\n\t" // counter == 15 ?
        "brne .+2"     "\n\t" // skip clr if not 15
        "clr r16"      "\n\t" // counter = 0    
        "out 0x3f,r10" "\n\t" // return SREG
        "reti"         "\n\t" // return from interrupt
        : 
        : 
    );
 
/* В инициализации: */
asm volatile (
        "mov r4,%0" "\n\t"
                "clr r31"    "\n\t"
        :
        : "r" (&port_out_table)
    );
В опциях компиляции: -ffixed-r30 -ffixed-r31 -ffixed-r10
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
02.11.2020, 13:44
Цитата Сообщение от pusyakaryagin Посмотреть сообщение
Тут немного не понял, что сравнивается в 4 инструкции, ведь r31 вроде как пуст.
ну... как пуст - ведь данная "addiw" работает с парой регистров [R31:R30]. Так что результат увеличения будет в младшем [R31].
Цитата Сообщение от pusyakaryagin Посмотреть сообщение
В опциях компиляции: -ffixed-r30 -ffixed-r31 -ffixed-r10
нормальное решение поздравляю с хорошей оптимизацией. Для мелких тинек вполне справедливо не учитывать старшие биты вообще, если ДШ не пишет другое. (кто-то здесь писал, что в AVR адреса зацикливаются, то есть старшие биты просто игнорируются).
0
451 / 176 / 29
Регистрация: 12.12.2020
Сообщений: 1,367
13.12.2020, 14:53
Может и не в тему.... делал я аппаратный шим для ругулировки подстветки светодиодной ленты. Тоже кстати на 2313. И был эффект мерцания, то есть так не видно, а когда перефирийным зрением смотришь..... да, типа надо бы частоту поднять. А как ее поднять то? А очень просто - я счетчик сделал не ++, а +2, то есть цикл стал считаться в два раза быстрее. Счетчик тот который у автора cnt.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.12.2020, 14:53

Измерение частоты и скважности ШИМ (Infineon XC2000)
Необходимо измерять частоту и скважность ШИМа в непрерывном режиме. Навскидку есть пара вариантов измерения частоты и скважности...

Программа для понижения/повышения частоты работы процессора?
Какая программа может стартуя вместе с виндовс автоматически понижать/повышать частоту работы процессора до заданных мной...

Оптимизация кода для повышения скорости выполнения?
Есть ли какая возможность в VBA замера производительности как в 1С с указанием относительного времени исполнения отдельных строк кода, что...

Оптимизация частоты ШИМа для управления приводами робота.
Из каких соображений можно определить оптимальную частоту ШИМ? При сильно низкой частоте двигатель будет вращаться рывками. При сильно...

Для повышения Тиц и Pr
Доброго времени суток, сколько ссылок должно ссылаться на мой сайт для повышения показателей Тиц и PR?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
37
Ответ Создать тему
Новые блоги и статьи
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru