Mega2560 PWM

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
Добрый всем!

Прошу помощи так как зашел в тупик.

Есть две ардуино мега 2560 от robotdyn (Robotdyn Mega +WiFi R3 ATmega2560+ESP8266.)

Изначально все работало прекрасно до тех пор пока не поиграл немного с регистрами таймеров (4 и 5)

Регистры были установлены следующие:
TCCR4B = TCCR4B & B11111000 | B00000001;
TCCR5B = TCCR5B & B11111000 | B00000001;

Мои предположения:
По ошибки или невнимательности было установлено значение для функции analogWrite больше 255 после чего перестала работать нормально функция analogWrite даже если удалить регистры из кода и проявлялась она в следующем.

Если исполнить код в противофазе значений:
C++:
void setup()
{

}

void loop()
{
for(int i = 1; i < 255; i+=10)
{
analogWrite(6, i);
analogWrite(44,255 - i);
delay(100);
}
}
То шим работает и ослик показывает все нормально.



Если исполнить код такой с одинаковым значением функции analogWrite в данном случаи 128:
C++:
void setup()
{

}

void loop()
{
for(int i = 1; i < 255; i+=10)
{
analogWrite(6, 128);
analogWrite(44,128);
delay(100);
}
}
То все также нормально работает как и задумано.



Но проблема кроется в следующем и проявляется только когда задействовано от 2 и более выводов с analogwrite
Для примера код с разными значениями функции то на обоих пинах тишина и нет никаких сигналов.
C++:
void setup()
{

}

void loop()
{
for(int i = 1; i < 255; i+=10)
{
analogWrite(6, 128);
analogWrite(44,200);
delay(100);
}
}
Разницы в работе от расположения в блоке setup или просто без цикла не играют никакой рои было опробовано.


Все эти скетчи пробывались уже без установки регистра таймеров. Замыканий внешних 100% небыло. Поведение подобное на двух платах, Подскажите куда копать потому что я потерялся. Так же пробывал через USBasp перезаписывать загрузчик но эффекта не последовало.

Спасибо за внимание и будущию помощь! рад буду любым наводкам.
 

Вложения

Последнее редактирование:

Arhat109

★★★✩✩✩✩
9 Июн 2019
381
128
Ой, ни помню ужо .. если не горит, то после 21-го залезу в даташит посмотрю, что Вы там намудрили.
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
Было бы очень замечательно, потому что две платы лежат обидно как то, уже месяц пытаюсь понять. А платы удобные да и хотелось бы понять почему так происходит=(
 

Старик Похабыч

★★★★★★✩
14 Авг 2019
2,021
511
Москва
Младшие 3 бита регистров (которые очищены и потом установлены в 001) отвечают за множитель таймера. При установке в 001 множитель отключен, вернее он равен 1. Начальное значение для меги я не знаю. для нано это, если не путаю, 64. Т.е. 011. Это может сильно влиять именно на шим, т.к. они связаны с таймером
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
Младшие 3 бита регистров (которые очищены и потом установлены в 001) отвечают за множитель таймера. При установке в 001 множитель отключен, вернее он равен 1. Начальное значение для меги я не знаю. для нано это, если не путаю, 64. Т.е. 011. Это может сильно влиять именно на шим, т.к. они связаны с таймером
Вы про эти регистры?
TCCR4B = TCCR4B & B11111000 | B00000001;
TCCR5B = TCCR5B & B11111000 | B00000001;
если да то они прекрасно работают для частоты 31KHz а в примерах которые я привел я не указывал никакие регистры и при этом не работают
 

Arhat109

★★★✩✩✩✩
9 Июн 2019
381
128
Нет. Это Control регистры таймеров. У каждого их по 3шт (xxA xxB xxC), за исключением 8-и битников. Это регистры "докуда считать" деятельность таймера, а потом "переключить" соответствующий каждому их них выход. Как раз в них пишет analogWrite(). Вообще-то они 16-и битные на этих таймерах.
Смотрите распиновку Меги, куда выведены 2-е каналы (B) 4 и 5 таймера. Вот ни этих ногах Вы и практикуетесь такой записью. Кстати, чиселко у вас получается 241, но Вы её пользуете как маску предыдущего значения.

В общем, что-то Вы напортачили где-то в ином месте. Эти 2 строчки мало на что влияют и уж тем более, никак ничего не фиксят между заливками ПО..
дело где-то в другом месте.

И да, 6 пин - это никак не 4 и не 5 таймер. Они оба сидят в дополнительном разъеме Меги2560 .. это после 22 номера.
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
Таймеры те, все работает нормально сбой произошел именно когда значение поставил больше 255
Без регистров обычно превышение ничего подобного не вызывает а просто берется значение например установили 500 тогда реально будет
500-255 = 245 вот 245 и будет выданно. да и после перепрошивки поидеи регистры сбрасываются, а тут я уже пробывал отчистить и память и перепрошил загрузчик но все остается на месте. При чем касается это не только тех таймеров которые трогал тоесть если я буду использовать порты которые подключены например к первому и второму таймеру результат будет таким же.
Безымянный.png
 
Последнее редактирование:

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
Счас заметил еще вот такое
При таком скейтче

C++:
void setup()
{
}

void loop()
{

  analogWrite(10, 200);
  analogWrite(11, 100);

}

10 пин просто выводит 5V без шима а 11 молчит

а если наоборот

C++:
void setup()
{
}

void loop()
{

  analogWrite(10, 100);
  analogWrite(11, 200);

}
то тишина на обоих пинах
 

Arhat109

★★★✩✩✩✩
9 Июн 2019
381
128
Машинка точно Мега2560 или Вы еспшную часть юзаете? .. хотя "как это?" .. то, что Вы пишете - просто фантастика. запостите весь скетч целиком после которого у Вас начались проблемы.. на обычной меге такого не может быть по-просту..
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
Машинка точно Мега2560 или Вы еспшную часть юзаете? .. хотя "как это?" .. то, что Вы пишете - просто фантастика. запостите весь скетч целиком после которого у Вас начались проблемы.. на обычной меге такого не может быть по-просту..
К сожалению точного скейча нету так как не сразу обратил внимание когда сломалось.
Но общий смсысл был такой

C++:
TCCR4B = TCCR4B & B11111000 | B00000001;
TCCR5B = TCCR5B & B11111000 | B00000001;

void setup()
{

}

void loop()

{
  analogWrite(6, 1000);
  analogWrite(44, 200);
}
Когда сломалась первая плата я думал что это я где то накосячил с подключением и произошло реально КЗ, но после второй платы которая была подключена только к ослику и больше не к чему произошло тоже самое и единственное что объединяет это ошибка со значением функции больше 255.

Я тоже уже весь мозг сломал как такое произошло и из за чего и почему задевает все пины на всех таймерах. И почему сброс не помогает.

И да мега работает в режиме простой меги только, без есп
 
Последнее редактирование:

Arhat109

★★★✩✩✩✩
9 Июн 2019
381
128
Это всё никак не может приводить к описываемым Вами эффектам. Искать стоит в ином месте, я уже отписал выше.

Сколько мучал типовую Мегу, имею 3 версии собственных разработок на базе этого камня, запаял уже больше 30 экземпляров .. каждый из них тестировался на все 100% функционала .. и ни разу не наблюдал, чтобы простой код программирования регистров таймеров каким-то ЧУДОМ сохранялся в ПЗУ камня .. это просто "фантастика".
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
Ну у меня мега одна от robotdyn а вторая точно такая же но другого производителя счас не помню. А вот стандартной меги у меня нет проверить не могу. Самое хреновое что я даже связь не пойму как такое может происходить... Ладно бы просто сохранились бы регистры и не стирались понятно было бы если бы шим просто тупо не работал. Но по отдельности порты работают, которые изминяются в цикле работают. А вот простым указанием не работает. При чем разное поведение если в первой функции указывать значение большее то шима нет но включается просто высокий уровень 5V на пине а второй молчит, и если наоборот меньший показатель чем у второго пина то просто тишина... После первой платы реально подумал может спалил что то так как подключал, но вторая плата воот вообще ни к чему не подключалась. И если указывать допустим эти таймеры и выставлять шим одинаковый то регистры норм отрабатывают на нужной частоте.
 

Wan-Derer

★★★★★✩✩
Команда форума
31 Июл 2018
1,472
305
Москва
wan-derer.ru
@adaly, Так проверь порты по отдельности. Запаяй на них светодиоды с резисторами. А напиши тест, которы гоняет бегущий огонёк и бегущую тень. Если какой-то порт "пробит", ты это увидишь. То что повреждены какие-то внутренние блоки - это нереально
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
@adaly, Так проверь порты по отдельности. Запаяй на них светодиоды с резисторами. А напиши тест, которы гоняет бегущий огонёк и бегущую тень. Если какой-то порт "пробит", ты это увидишь. То что повреждены какие-то внутренние блоки - это нереально
На второй плате КЗ исключен. А по теме теста он не пройдет. шима просто не будет и тень не создаться это на всех пинах с шимом. Не важно к какому таймеру они подключены. Но я сегодня куплю светодиоды и проверю как вы предложили. Может что то интересное выявится.
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
@adaly, Я говорю не про ШИМ, а про проверку самих портов
А сами порты пашут. И пашут с шимом но только если в скетче указан только одна строчка кода с analogWrite на одном пине. Если 2 и больше порта то все перестает работать.

ПО на стороне компьютера не виновато. Если грузить этот же код в другую плату то все отрабатывает нормально.
 

Wan-Derer

★★★★★✩✩
Команда форума
31 Июл 2018
1,472
305
Москва
wan-derer.ru
@adaly, Я предлагаю проверить все (несколько) порты вместе чтобы увидеть взаимное влияние если оно есть
 

Старик Похабыч

★★★★★★✩
14 Авг 2019
2,021
511
Москва
и ни разу не наблюдал, чтобы простой код программирования регистров таймеров каким-то ЧУДОМ сохранялся в ПЗУ камня .. это просто "фантастика".
Я не проверял, играя с делителями частоты я всегда возвращал его в исходное положение , от греха подальше ) Но если они не сохраняются в ппзу, то это отлично. Можно играть не боясь и потом ресетом все сбросить взад
 

Arhat109

★★★✩✩✩✩
9 Июн 2019
381
128
@Старик Похабыч, У камня есть ПЗУ программы, которая сохраняется в нем совершенно железно, если камень исправный. Гарантия изготовителя в районе 20 лет "лежания" или считывания. Программа.
Если в ней(!) есть перенастройка, то она будет запусукаться после каждого ресета ЗАНОВО. И только.
Как только залили иную программу ничего камень про прошлую не помнит от слова совсем.

Ещё есть EEPROM - ПЗУ данных. В него то что пишется НИ НА ЧТО само не влияет. От слов "ни разу". Только то, что программой СЧИТЫВАЕТСЯ "ручками" и ими же, программными ручками рассовывается куда сказано. ВСЁ, тут тоже точка.

Базовая (по включению) настройка и установка ВСЕХ внутренних блоков, включая таймеры, предделители производится кнопкой ресет, в т.ч. и по включению питания .. ей же! Время ресета прописано в даташите, поэтому на него вешают кондер или поднимают питание на камне со скоростью, также нарисованной в даташите. Тут тоже ВСЁ.

Никакой фантастики, как пишет автор типа "залил программу", ПЕРЕЗАЛИЛ другую и НЕ работает - наблюдать можно только приняв много на грудь или во сне.

Вариант с выходом из строя из-за превышения нагрузки по пину (20/40мА - предел и не более 5 пинов сразу суммарно в 200мА) - возможно. Но, в таком разе, оно СОВСЕМ не будет работать! Ни вдвоем ни по одиночке.. а тут автор пишет что "так работает" а "так нет". Причем на примитивном коде.

Хоть кто-то воспроизвел косяк? У меня сейчас нет дуньки под рукой .. не могу.
 

Wan-Derer

★★★★★✩✩
Команда форума
31 Июл 2018
1,472
305
Москва
wan-derer.ru
C++:
TCCR4B = TCCR4B & B11111000 | B00000001;
TCCR5B = TCCR5B & B11111000 | B00000001;

void setup()
{

}

void loop()

{
  analogWrite(6, 1000);
  analogWrite(44, 200);
}
Очень странно что это код компилируется. Было бы интересно взглянуть в какие ассемблерные команды он переводится. К сожалению, у меня нет времени разбираться как это посмотреть, но по идее должно быть что-то такое:

C++:
ldi R16, data
out port, R16
т.е. в регистр загружается число, а потом регистр записывается в порт, отвечающий за ШИМ. Регистр 8-разрядный! В него в принципе невозможно загрузить больше 255. Т.е. этот код просто не может быть исполнен, а что уж туда загрузилось - ХЗ.
А то что это что-то испортило МК - это вообще невозможно. Разве что ты открыл какую-то супер-пупер уязвимость. Ну или лб этом есть где-то в Errata :)
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
@adaly, Я предлагаю проверить все (несколько) порты вместе чтобы увидеть взаимное влияние если оно есть
C++:
int ledPins[] = {2,3,4,5,6,7,8,9,10,11,12,13};
void setup()
{
for(int index = 0; index <= 12; index++)
  {
    pinMode(ledPins[index],OUTPUT); 
  }
}
void loop()
{
for(int index = 0; index <= 12; index++)
  {
    digitalWrite(ledPins[index], HIGH);
    digitalWrite(ledPins[index+1], HIGH);
    delay(400);            
    digitalWrite(ledPins[index], LOW);
    digitalWrite(ledPins[index+1], LOW);
  }
}

А вот пример с шимом.
В первые пол минуты все происходит нормально, а во второй половине как раз проблема
 
Последнее редактирование:

Wan-Derer

★★★★★✩✩
Команда форума
31 Июл 2018
1,472
305
Москва
wan-derer.ru
@adaly, не очень понятно: в первом видео загораются по два СД, а должны по одному? Тогда это признак пробитых портов.
 

adaly

✩✩✩✩✩✩✩
8 Дек 2019
14
1
@adaly, не очень понятно: в первом видео загораются по два СД, а должны по одному? Тогда это признак пробитых портов.
по два и должны
digitalWrite(ledPins[index], HIGH);
digitalWrite(ledPins[index+1], HIGH);
в первом все корректно работает, во втором первая половина тоже корректно (два светодида один идет от максимума к минимуму, а второй наоборот) , а вот во второй части там где просто задать разную яркость диодам, загорается вместо четырх лед, горит один. И этот один немноо мерцает.
 
Последнее редактирование:

Arhat109

★★★✩✩✩✩
9 Июн 2019
381
128
@Wan-Derer, Нормально он будет компилироваться. Открываем io.h, видим что для Мега2560 подключается файл iom2560.h, в котором основные макросы берутся из iomxx0_1.h и смотрим что представляют из себя макросы:

#define TCCR4B _SFR_MEM8(0xA1), в свою очередь определено в sfr_defs.h как (режим несовместимости с асмом, ибо С/С++):

#define _SFR_MEM8(mem_addr) _MMIO_BYTE(mem_addr), и выше находим:
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))

, подставляя одно в другое получаем:
#define TCCR4B (*(volatile uint8_t *)(0xA1))

Разворачивая оператор присваивания получаем с учетом предвычисления констант компилятором:
(*(volatile uint8_t *)(0xA1)) = (*(volatile uint8_t *)(0xA1)) & B11111001;

Что может быть развернуто в код только так, ибо volatile:
lds Rxx, 0x00A1 ; получить значение регистра таймера
lds Ryy, 0xF9 ; загрузить константу в другой регистр
and Rxx, Ryy ; домножить побитово
sts Rxx, 0x00A1 ; загрузить результат в регистр взад.

и никаких чудес. Остается только смотреть даташит что за регистр по этому адресу .. а там (и тут я был не прав, забыл ужо):

(0xA1) TCCR4B ICNC4 ICES4 reserved WGM43 WGM42 CS42 CS41 CS40 стр.160, т.е. имеем установку:

ICNC4=1, ICES4=1, reserved=1, WGM43=1, WGM42=1, CS42=0, CS41=0, CS40=1

на стр. 160 имеем:
• Bit 7 – ICNCn: Input Capture Noise Canceler
Setting this bit (to one) activates the Input Capture Noise Canceler. When the Noise Canceler is
activated, the input from the Input Capture Pin (ICPn) is filtered. The filter function requires four
successive equal valued samples of the ICPn pin for changing its output. The input capture is
therefore delayed by four Oscillator cycles when the noise canceler is enabled.

Бит фильтрации ноги "захват таймера" по 4 замерам и соответственно задержка на 4 такта таймера выставления значения в нем при успешной попытке захвата значения. Кмк, на столько же будет задержано и прерывание по захвату таймера4

• Bit 6 – ICESn: Input Capture Edge Select
This bit selects which edge on the Input Capture Pin (ICPn) that is used to trigger a capture
event. When the ICESn bit is written to zero, a falling (negative) edge is used as trigger, and
when the ICESn bit is written to one, a rising (positive) edge will trigger the capture.
When a capture is triggered according to the ICESn setting, the counter value is copied into the
Input Capture Register (ICRn). The event will also set the Input Capture Flag (ICFn), and this
can be used to cause an Input Capture Interrupt, if this interrupt is enabled.
When the ICRn is used as TOP value (see description of the WGMn3:0 bits located in the
TCCRnA and the TCCRnB Register), the ICPn is disconnected and consequently the input cap-
ture function is disabled.

Нога захват таймера работает на генерацию прерывания: 0 - по заднему фронту захвата, 1 - по переднему фонту захвата. Прерывания должны быть разрешены в ICF бите.

• Bit 5 – Reserved Bit
This bit is reserved for future use. For ensuring compatibility with future devices, this bit must be
written to zero
when TCCRnB is written.

Дальше можно не смотреть. Что там погорело в таймере или перклинило и как он будет дальше работать - производитель, насколько помню НЕ ГАРАНТИРУЕТ.

В общем, тема - прекрасный образчик того, что ПРЕЖДЕ ЧЕМ ЛЕЗТЬ в регистры напрямую НАДО ЧИТАТЬ RTFM.

Автор, похоже Вы "сам себе злобный Буратино" (ССЗБ) :)

P.S. Тем не менее посмотрел дальше .. автор, это просто фантастика! ГДЕ Вы взяли ТАКИЕ настройки этого регистра?!? :)

По умолчанию, 16-и битный таймер в Wiring настраивается на режим "байтовый fast PWM mode" (режим №5), здесь изменяются 2(два!) старших бита WGM43 = WGM42=1 и режим превращается (брюки превращаются) .. в режим №13, т.е. RESERVED

Занавес.
 
Последнее редактирование:
  • Лойс +1
Реакции: adaly