честно говоря, вы тут слишком много понаписали и все запутали.
1 измерение АЦП это максимум 1023. 100 измерений в секунду за час дадут сумму максимум 1023*60*60*100=368280000 это unsigned long. эта переменная сможет накапливать ваши измерения в течение 11 часов максимум, потом переполнится.
нет никакой проблемы суммировать и сравнивать unsigned long для 8-битного МК.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
честно говоря, вы тут слишком много понаписали и все запутали.
возможно я виноват - признаюсь попытаюсь еще раз объяснить цифра которая видна на экране состоит из 2 переменных. значение до запятой это 1-я переменная типа int - будет цифра на пределе инта = 65535 значение после запятой это 2-ая переменная типа char - будет цифра от 0 до 99 также в бэкграунде будет 3-ая переменная в которую будут суммироваться значения АЦП, значение этой переменной после каждого сложения с значением АЦП будет сравниваться с константой 360 000. Если значение 3-ей переменой перевалит за 360 000 тогда из нее вычитается 360 000, а 2-ая переменная инкрементируется. Когда вторая переменная достигнет 100 она обнуляется, а первая переменная инкрементируется.
Вопрос был как лучше оптимизировать все потому что из-за большой константы 360 000 вынужден третью переменную сделать типа long. А это 100 раз в секунду работать с такой огромной переменной это нагрузка на MK который имеет еще кучу задач.
И понимаю чтоб уменьшить константу надо увеличить вторую переменную до уровня int и сделать ее в 10 раз больше то есть будут миллиамперы час. Таким образом константа сравнения будет в 10 раз меньше и смогу уместить 3-ю переменную в размер int.
А вторую переменную перед показом на экран буду делить на 10.
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Пн авг 10, 2015 07:00:31
Модератор
Карма: 90
Рейтинг сообщений: 1289
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4510 Откуда: Планета Земля
Рейтинг сообщения:0 Медали: 1
amd9800 писал(а):
с такой огромной переменной это нагрузка на MK
Госпадяяяя... какая же это нагрузка - сравнение, вычитание, сложение, ... ? Тем более с константами Делайте long и не парьтесь...
PS: Вы делаете проблему буквально из ничего. Что в этой теме, что в других. Вы, для начала, сделайте, а потом когда проблема появится - будете уже её решать.
В теме http://radiokot.ru/forum/viewtopic.php?f=61&t=119254 был поднят вопрос об инверсии порядка следования битов в слове на обратное (реверсия слова). Мне посоветовали продублировать ответ в этой теме, что я и делаю.
Первое, что приходит на ум, это реализовать такую функции с помощью цикла с побитовым просмотром исходного слова, однако в книге Генри Уоррена "Алгоритмические трюки для программистов" можно найти вариант этой операции без использования цикла. Для реверсии байта функция будет выглядеть следующим образом:
uint8_t ReverseByte(uint8_t b) { uint8_t ret;
ret = ((b & 0x55)<<1) | ((b & 0xAA)>>1); ret = ((ret & 0x33)<<2) | ((ret & 0xCC)>>2); ret = ((ret & 0x0F)<<4) | ((ret & 0xF0)>>4);
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
цифра которая видна на экране состоит из 2 переменных. значение до запятой это 1-я переменная типа int - будет цифра на пределе инта = 65535 значение после запятой это 2-ая переменная типа char - будет цифра от 0 до 99 также в бэкграунде будет 3-ая переменная в которую будут суммироваться значения АЦП...
По мне, гораздо проще объявить 1 переменную ΣCODE как 32 разрядную и результат получать по выражению 100*RES=ΣCODE/K, где 100 - число измерений в единицу времени K - коэффициент преобразования. Децимальную точку принудительно ставить после единиц. Например K=130, т.е. 1A соответствует значение 130 единиц АЦП и входном токе 7.86А в сумматоре ΣCODE должно накопиться 7.86*130*100=102180 и 100*RES=ΣCODE/K=102180/130=786 Можно избавиться от операции деления на константу, заменив её умножением. В данном случае разрядность ΣCODE не изменится.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
я признателен за попытку помочь, но мне кажется что вы запутались и не заметили что перепутали ампер*часы с амперами. Поэтому ваши расчеты получились не правильными. Также у вас в расчетах появилось деление, наверное на фоне деления - long уже точно не проблема. Я хочу разгрузить МК более оптимизированным кодом, а не загрузить дополнительно.
Все таки оптимизировал экономия скомпилированной программы примерно 40 байт. Вместо 3 переменной unsigned long. Будет 3 переменная unsigned int и 4 переменная unsigned char.
Код:
Ah - первая (unsigned int) cAh - вторая (unsigned char) tempAh - третья (unsigned int) tempAhz - четвертая (unsigned char)
Код:
tempAh=tempAh+Amp; if (tempAh>35999) { tempAh=tempAh-36000; tempAhz++; if (tempAhz>9) { tempAhz=0; cAh++; if (cAh>99) { cAh=0; Ah++; } } }
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Сб авг 15, 2015 05:08:08
Опытный кот
Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42 Сообщений: 744 Откуда: Караганда, Казахстан
Рейтинг сообщения:2
Const14 писал(а):
Немного отвлеку вас от текущего обсуждения...
В теме http://radiokot.ru/forum/viewtopic.php?f=61&t=119254 был поднят вопрос об инверсии порядка следования битов в слове на обратное (реверсия слова). Мне посоветовали продублировать ответ в этой теме, что я и делаю.
Первое, что приходит на ум, это реализовать такую функции с помощью цикла с побитовым просмотром исходного слова, однако в книге Генри Уоррена "Алгоритмические трюки для программистов" можно найти вариант этой операции без использования цикла.
Да, на Си оно выглядит довольно красиво. Однако, как мне кажется, реализация этого дела займет гораздо больше 16 машинных команд того же АВР. Тогда, как банальное повторение 8 раз пары команд rol r0 ror r1 легко и непринужденно вывернет наизнанку содержимое R0 и поместит его в R1. Про 8051 не скажу, не знаю я его, но, даже если у него есть сдвиги на заданное число разрядов, а не на один, все равно все это довольно сложно, в отличие от
_________________ Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Сб сен 05, 2015 20:22:04
Держит паяльник хвостом
Карма: 15
Рейтинг сообщений: 70
Зарегистрирован: Ср мар 28, 2012 21:45:24 Сообщений: 904 Откуда: ВО
Рейтинг сообщения:0
Вот так можно менять значения установки часов для серии DS1307 - DS3232M, не прибегая к таблицам, и BCD->HEX->BCD В rab первое значение, все остальное в rab1 , кроме 0
Код:
;************************************************** ;* ;;/PLUS DATA;;* * ;************************************************** Clock_Plus: push temp ld temp,X ;| Получаем значение add temp,rab ;| Прибавляем константу для счёта в BCD subi temp,-1 ;| Прибавляем единицу brhc Plus_Chng ;| Проверяем переход с F->0 (перенос) SAVE_PLUS: sub temp,rab ;| Вычитаем константу и получаем упакованный BCD cpse temp,rab1 ;| Сравниаем с максимально допустимым rjmp END_PLUS ;|для этого значения часов sbrc Flags1,fl_Chng_Way ;+ проверяем флаг направления ldi temp,1 ;|Если флаг установлен загружаем (1-день,число,месяц) sbrs Flags1,fl_Chng_Way ;+ проверяем флаг направления clr temp ;|Если флаг сброшен загружаем (0-час,минута,год) END_PLUS: st X,temp ;| и возвращаем на место rcall OUT_Clock_LCD ;/ Выводим на LCD новое значение pop temp ret Plus_Chng: subi temp,-6 ;|Если в младшей тетраде 0 прибавляем 6) rjmp SAVE_PLUS ;************************************************** ;* ;;/MINUS DATA;;* * ;************************************************** Clock_Minus: push temp ld temp,X ;| Получаем значение cpse temp,zero ;| Проеряем на 0-час,минута,год rjmp PC+2 MOVE_MINUS: mov temp,rab1 ;| Равны , копируем в temp максимально допустимый предел add temp,rab ;| Прибавляем константу для счёта в BCD subi temp,1 ;| Вычитаем единицу sub temp,rab ;| Вычитаем константу и получаем упакованный BCD brhs Minus_Chng ;| Проверяем переход с 0->F (заём) cpse temp,zero ;| Проверяем на 0-день,число,месяц rjmp END_MINUS sbrc Flags1,fl_Chng_Way ;+ проверяем флаг направления ;| Если при устан. флаге temp=0, меняем значение на максимально возможное и снова на математику rjmp MOVE_MINUS END_MINUS: st X,temp rcall OUT_Clock_LCD ;/ Выводим на LCD новое значение pop temp ret Minus_Chng: subi temp,6 ;| Куда же без числа 6 rjmp END_MINUS
Раз уж зашла речь о часах, во многих процессорах предусмотрены операции для BCD арифметики, что позволяет упростить код. Например, вот так можно увеличивать значения часов H (переменная определённая в RAM) на 1 по модулю 24 в архитектуре 8051 (уменьшение пишется аналогично). Собственно, хитрости в кодах ниже нет - скорее стандартная практика.
Код:
mov A, H ; load H into ACC add A, #1 ; increment the value da A ; decimal adjust to BCD cjne A, #0x24, cont ; is maximum reached? clr A ; YES - reset A to 0 cont: mov H, A ; save updated value
Oчень похоже это выглядит в HCS08 и подобных:
Код:
lda H ; load H into ACC add #1 ; increment the value daa A ; decimal adjust to BCD cbeqa #0x24, rest ; is maximum reached? bra cont ; NO - continue rest: clra ; YES - reset A to 0 cont: sta H ; save updated value
У MSP430 можно все сделать прямо в памяти, и, конечно, в регистрах:
Код:
clrc ; reset C flag dadd.b #1, &H ; increment H in BCD cmp.b #0x24, &H ; is maximum reached? jne cont ; NO - continue clr.b &H ; YES - reset H to 0 cont:
Ну и для Кортексов M3/M4. У них нет команд для работы с BCD, но многие операции могут выполняться условно.
Код:
ldr R1, =H ; R1 = address of H ldrb R0, [R1] ; R0 = hours add R0, #1 ; increment the value in R0 mod 24 tst R0, #0x0A ; need decimal adjust? addne R0, #6 ; YES - do it cmp R0, #0x24 ; is maximum reached? moveq R0, #0 ; YES - reset R0 to 0 strb R0, [R1] ; save result in RAM
Ser60 Возможно есть смысл (как ранее предлагалось и в этой теме) открыть отдельный раздел, где выкладывать типовые алгоритмы без привязки к конкретной системе команд конкретного МК - в виде пошаговых текстовых описаний (подобия ранних схем алгоритмов начала эры МК/ПК). А доводку такого шаблона пользователь сможет выполнить самостоятельно уже в привязке к собственному проекту (модель памяти и ресурсов в конкретной задаче с конкретным МК)..?
Весьма неплохая "копилка шаблон-алгоритмов" получиться может, особо если отредактировать в "дружественно-конструктивном" режиме базовые правила описания алгоритмов.
Неплохая идея. Думаю, будет полезно начинающим и не только. Но мне заниматься ведением этой темы некогда. Если возьмётесь, будет замечательно. Помимо описания алгоритмов может стоит будет привести наброски примеров их реализации под популярные архитектуры. В этом случае мой предыдущий пост будет уместно перенести туда.
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Пн сен 07, 2015 09:28:00
Друг Кота
Карма: 67
Рейтинг сообщений: 1012
Зарегистрирован: Чт сен 18, 2008 12:27:21 Сообщений: 18810 Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения:0 Медали: 1
Не знаю, в чём затык с часами. Я сделал поразрядную установку с проверкой (отдельно время, отдельно дата): десятки дней (0...3), единицы дней (0...9), десятки месяцев (0 или 1), ед. мес (0...9), года (0...99 поразрядно); Десятки часов (0...2), ед.ч. (0...9), дес. мин. (0...5), ед. мин. (0...9).
_________________ [ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ] Измерить нннада?
В теме http://radiokot.ru/forum/viewtopic.php?f=61&t=119254 был поднят вопрос об инверсии порядка следования битов в слове на обратное (реверсия слова). Мне посоветовали продублировать ответ в этой теме, что я и делаю.
Первое, что приходит на ум, это реализовать такую функции с помощью цикла с побитовым просмотром исходного слова, однако в книге Генри Уоррена "Алгоритмические трюки для программистов" можно найти вариант этой операции без использования цикла. Для реверсии байта функция будет выглядеть следующим образом:
Код:
uint8_t ReverseByte(uint8_t b) { uint8_t ret;
ret = ((b & 0x55)<<1) | ((b & 0xAA)>>1); ret = ((ret & 0x33)<<2) | ((ret & 0xCC)>>2); ret = ((ret & 0x0F)<<4) | ((ret & 0xF0)>>4);
return ret;
А где сдвиг третьего бита?! А ну понятно, он как-то сам хитро сдвигается. Код скорее головоломка забавная. Нагляднее в цикле написать или по простому
Код:
ret = (b<<8) ret = ret | ((b & 10b)<<6) ret = ret | ((b & 100b)<<4) ...
Хоть в отладчике можно посмотреть что делается, а не каша из бит, но быстрее работает понятно, может на 20%
Вариант программной "безджиттерной" генерации интервалов на основе векторно - условных переходов. Как частный случай - генерация пакета для ленты WS2812 c фазовой манипуляцией: viewtopic.php?p=2858887#p2858887 В принципе позволяет стабилизировать период с точностью до одного командного цикла. Альтернатива накапливаемой ошибке при применении стандартных команд перехода по условию, для которых существует правило разного времени исполнения в случаях истина или ложь. Конструкция конечно более громоздкая по количеству команд, зато время выполнения весьма равномерно распределено.
Уж не знаю, насколько это хитро, но давно использую для математических вычислений на МК следующее свойство: 1. Если сдвинуть двоичное число на один разряд влево, то это равносильно умножению на два. Это общеизвестно. 2. Если сдвинуть двоичное число на один разряд вправо, то это равносильно делению на два. Это тоже общеизвестно. 3. Если сдвигать двоичное число на один разряд вправо столько раз, сколько нужно, чтобы результат стал равен единице, то это количество раз будет логарифмом по основанию 2 от нашего числа. А про это забывают.
Понятно, что целочисленное заначение логарифма весьма не точно, но когда точность не требуется, позволяет очень быстро выполнять операции возведения в степень или извлечения корня.
_________________ Не ошибается только то, кто ничего не делает. Тот, кто признает свои ошибки, на них учится. Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Может уже было? Исключительно для собственных протоколов передачи данных. Многим известно что для защиты целостности передачи данных используется контрольная сумма. В общем случае используют известные методы CRC8,CRC16,CRC32 с разными полиномами. В некоторых контроллерах есть уже встроенные блоки подсчета CRC, но часто нужно самому софтово ее считать. И мне тоже понадобилось. Физический смысл CRC - циклическая сумма остатков от деления байта (слова) на известный полином (8,16,32 бит). Википедия все красиво описывает. Когда-то я при передаче пакетов USART по воздуху так и писал crc = (crc+data)%POLINOM; и в конце пакета добавлял в передачу CRC. Сам расчет контрольной суммы занимает определенное время, особенно деление. Для ускорения процесса используют таблицы с частным для нужного полинома. Я сейчас использую STM32. Там тоже тратится время на деление, но вот умножение делается за один такт! Пришла идея заменить деление умножением с отбрасыванием "целой" части и приведением результата к нужному типу данных. Получилась такая строка для CRC8: crc = (uint8_t)(0xff & (((uint8_t)(0xff & (crc+data)))*POL)); где POL полином контрольной суммы,задается в дефайнах, у меня 0х31. Все это компилируется в 5 ассемблерных команд и выполняется примерно за 8 тактов. Передача проходит четко. Вот так выглядит обработчик прерывания USART для захвата пакета в 80 байт с преамбулой void USART1_IRQHandler (void) { if (USART1->ISR & USART_ISR_RXNE) data = USART1->RDR; if (rf_stat == 2) { rx_buf[r_ptr] = data;r_ptr++; if(r_ptr > 80) { if (crc == rx_buf[80]) rx_buf_rdy = 1; else rx_buf_rdy = 0; crc = 0,r_ptr = 0,rf_stat = 0; } else crc = (uint8_t)(0xff & (((uint8_t)(0xff & (crc+data)))*POL)); } else if ((rf_stat == 1) && (data == 0xD4)) rf_stat++; else if ((rf_stat == 0) && (data == 0x2D)) rf_stat++; };
0x2D и 0xD4 старт пакета,rx_buf_rdy-флаг готовности,rf_stat - статус разбора пакета. Естественно от устройства с формированием CRC таким-же способом.
вот здесь я рассказал о своем принципе создания массивов без массивов ну, то есть когда вы не связаны по рукам и ногам тем, что статический массив целиком располагается в одном файле и невозможно никак задавать входящие в него элементы в разных местах проекта. если подобная проблема вас достала (я о желании перестать помнить о размере массива, о том, в каком файле он определен, о желании наполнять массив по частям в тех местах, где одна из частей понадобилась) - рекомендую почитать.
подход может быть полезен при разработке всяких парсеров или интерпретаторов строк, организации системы меню или иных случаев с обязательным перебором элементов массива для нахождения нужного из имеющихся элементов.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Может уже было? Исключительно для собственных протоколов передачи данных. Многим известно что для защиты целостности передачи данных используется контрольная сумма. В общем случае используют известные методы CRC8,CRC16,CRC32 с разными полиномами. В некоторых контроллерах есть уже встроенные блоки подсчета CRC, но часто нужно самому софтово ее считать. И мне тоже понадобилось.
Еще проще просто сумма, качество обнаружения ошибки падает, но не критично, я проверял, зато какая простота https://habr.com/ru/post/278171/
CRC полноценная кстати не намного дольше считается. Там деление вырождается в 8 операций смещения бита вправо и 8 опраций XOR. Как я понимаю смотрим младший бит, если он 1 то делаем XOR с полиномом. Потом смотрим предпоследний бит, и если он 1 то делаем XOR с полиномом. https://ru.wikipedia.org/wiki/%D0%A6%D0 ... 0%BE%D0%B4
Вот если бы считали 16 или 32 бит контрольную сумму, тут выигрыш был бы значительным.
И проверки алгоритма у вас нет, нужно собрать статистику, имитируая передачу миллиона сбойных пакетов, с 1,2,3..10 сбойными битами. Может полином быть выбран неудачно.
Сейчас этот форум просматривают: maxlab и гости: 29
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения