SysInfo for Arduino

arduinec
Offline
Зарегистрирован: 01.09.2015

SysInfo for Arduino

Пришли ко мне с Алиэкспресс в одной посылке несколько Arduino Pro Mini 5В+16МГц и 3,3В+8МГц. Внешне абсолютно одинаковы, различаются лишь непонятными буковками на кварце и стабилизаторе напряжения.
Проблему с их определением, разумеется, я решил: подал 9В (от Кроны) на вход RAW и померил напряжение на VCC (получил 3,3 и 5 вольт).
Позже задался вопросом: можно ли с помощью самой Ардуины померить внешнее напряжение и частоту. Оказалось можно.
Для определения напряжения питания измеряется внутренний источник опорного напряжения 1,1В при внешнем опорном напряжении.
Для вычисления частоты запускается пустой цикл (на 10 тысяч значений) и измеряется время его работы.

Когда-то давным-давно на PC была лишь DOS, а для тестирования компьютера удобно было использовать Norton Utilities. В этот комплект входила утилита SysInfo, которая выдавала системную информацию о компьютере.
Вот и возникла идея: совместными усилиями сделать аналогичный скетч для Ардуино. По-моему он был бы более полезен, чем простой Blink.

arduinec
Offline
Зарегистрирован: 01.09.2015

Версия 1.00

// SysInfo for Arduino
#define Version 1.00

void setup()
{
  Serial.begin(9600);

  Serial.print("SysInfo for Arduino version ");
  Serial.println(Version);
  Serial.println();

  VCC();
  Frequency();
}

void loop() {}

void VCC()
{
  #define Vref 1100
  int mvVcc;

  ADMUX = 1<<REFS0 | 0x0E;
  ADCSRA = (1<<ADEN) | (1<<ADATE) | (1<<ADSC) | 5;
  delay(1);
  mvVcc = (1023L * Vref) / ADC;

  Serial.print("VCC = ");
  Serial.print(mvVcc);
  Serial.println(" mV");
  Serial.println();
}

void Frequency()
{
  unsigned long ustime1, ustime2;
  int i, mhzFreq, iMax = 10000;

  Serial.print("F_CPU = ");
  Serial.println(F_CPU);

  ustime1 = micros();
  for(i=iMax; i>0; i--) __asm__("nop\n\t");
  ustime2 = micros();
  mhzFreq = 5 * (long)iMax / (ustime2 - ustime1) + 1;

  Serial.print("Frequency = ");
  Serial.print(mhzFreq);
  Serial.println(" MHz");
  Serial.println();
}

Вместе с реальной частотой выводится программно задаваемая F_CPU.

arduinec
Offline
Зарегистрирован: 01.09.2015

Добавил тестирование пинов.
Версия 1.01

// SysInfo for Arduino
#define Version 1.01

void setup()
{
  Serial.begin(9600);

  Serial.print("SysInfo for Arduino version ");
  Serial.println(Version);
  Serial.println();

  VCC();
  Frequency();
  TestPins();
}

void loop() {}

void VCC()
{
  #define Vref 1100
  int mvVcc;

  ADMUX = 1<<REFS0 | 0x0E;
  ADCSRA = (1<<ADEN) | (1<<ADATE) | (1<<ADSC) | 5;
  delay(1);
  mvVcc = (1023L * Vref) / ADC;

  Serial.print("VCC = ");
  Serial.print(mvVcc);
  Serial.println(" mV");
  Serial.println();
}

void Frequency()
{
  unsigned long ustime1, ustime2;
  int i, mhzFreq, iMax = 10000;

  Serial.print("F_CPU = ");
  Serial.println(F_CPU);

  ustime1 = micros();
  for(i=iMax; i>0; i--) __asm__("nop\n\t");
  ustime2 = micros();
  mhzFreq = 5 * (long)iMax / (ustime2 - ustime1) + 1;

  Serial.print("Frequency = ");
  Serial.print(mhzFreq);
  Serial.println(" MHz");
  Serial.println();
}

void TestPins()
{
  #define FIRST_PIN 0
  #define LAST_PIN 19

  Serial.println("Test of short circuit on GND or VCC:");

  for(byte pin = FIRST_PIN; pin <= LAST_PIN; pin++)
  {
    if(pin < 10) Serial.print("Pin:  ");
    else Serial.print("Pin: ");
    Serial.print(pin);

    pinMode(pin, OUTPUT);
    digitalWrite(pin, 0);
    Serial.print("    Low: ");
    if(!digitalRead(pin)) Serial.print("Ok  ");
    else Serial.print("Fail");

    digitalWrite(pin, 1);
    Serial.print("  High: ");
    if(digitalRead(pin)) Serial.print("Ok  ");
    else Serial.print("Fail");

    pinMode(pin, INPUT_PULLUP);
    Serial.print("  Pull Up: ");
    if(digitalRead(pin)) Serial.print("Ok  ");
    else Serial.print("Fail");

    Serial.println();
    pinMode(pin, INPUT);
  }
 
  Serial.println();
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Какое-то немного странное тестирование.

Если контроллер сконфигурирован правильно (установка фьюзов и пр.), то результаты измерений, возможно, правильно отражают реальное положение дел. Если же нет - что мы получим, неизвестно. А.т.к. перепрошивка контроллера - стандартная процедура, вероятность того, что все сконфигурировано правильно, существенно ниже, чем было бы в случае с ПК.

По поводу частоты - есть еще один способ измерения, гораздо более быстрый: определяем, с какой дискретностью возвращается значение micros(): если 4, значит, 16 МГц, если 8 - 8 МГц.

Ну и наиболее интересная информация - тип процессора (объемы различных видов памяти, наличие дополнительной внешней памяти и пр.) вообще выпущены из внимания. Не говоря уже о характеристиках подключенной периферии.

arduinec
Offline
Зарегистрирован: 01.09.2015

andriano пишет:

Ну и наиболее интересная информация - тип процессора (объемы различных видов памяти, наличие дополнительной внешней памяти и пр.) вообще выпущены из внимания.

Вот именно. На форуме есть более крутые специалисты по процессорам и памяти чем я, поэтому и было предложено (в посте 0) совместно расширить данный скетч.

andriano пишет:

По поводу частоты - есть еще один способ измерения, гораздо более быстрый: определяем, с какой дискретностью возвращается значение micros(): если 4, значит, 16 МГц, если 8 - 8 МГц.

Если andriano приложит код, реализующий данный алгоритм, то добавим его в скетч.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Видите ли, arduinec, я предложил идею, основываясь исключительно на документации: https://www.arduino.cc/en/Reference/Micros

Идея, как мне кажется, изложена достаточно понятно, чтобы ее мог воплотить любой желающий.

Но если мы говорим о создании конкретного кода, то я к такому повороту не готов ввиду полного отсутствия у меня 8 МГц кристаллов - не на чем проверить.

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

arduinec
Offline
Зарегистрирован: 01.09.2015

Посмотрел исходный код micros():

unsigned long micros() {
  unsigned long m;
  uint8_t oldSREG = SREG, t;

  cli();
  m = timer0_overflow_count;

  #if defined(TCNT0)
    t = TCNT0;
  #elif defined(TCNT0L)
    t = TCNT0L;
  #else
    #error TIMER 0 not defined
  #endif

  #ifdef TIFR0
    if ((TIFR0 & _BV(TOV0)) && (t < 255)) m++;
  #else
    if ((TIFR & _BV(TOV0)) && (t < 255))  m++;
  #endif

  SREG = oldSREG;
	
  return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

Там используется макрос:
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )

F_CPU задаётся программно (при прошивке загрузчика) и нам известна, поэтому дискретность micros() нам ничего не даёт.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Значит, проще всего вывести в Serial значение F_CPU и не парить себе мозг.

Т.к. если эта константа определена не для нашего камня, то и результат измерения выполнения будет точно такой неправильный.

Другими словами, оба метода измерения дают один и тот же результат.

arduinec
Offline
Зарегистрирован: 01.09.2015

andriano пишет:

Значит, проще всего вывести в Serial значение F_CPU и не парить себе мозг.

F_CPU в сериал выводится вместе с рассчитанной частотой. Хотелось бы получить реальную частоту, не зависящую от F_CPU. Может специалисты по таймерам что-нибудь подскажут.

arduinec
Offline
Зарегистрирован: 01.09.2015

Провёл эксперимент. На макетной плате у меня стоит Atmega328p в DIP-корпусе с прошивкой Arduino Uno. Не меняя прошивку, поменял у неё кварц с 16 на 8 МГц. Для связи на COM-порте пришлось поменять скорость на 4800.
SysInfo выдала: Frequency = 16 MHz (F_CPU = 16000000).
Получается, что Ардуина сама не может определить свою частоту, а лишь руководствуется программно задаваемой F_CPU.
 

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

Навскидку - частоту реально посчитать таймером, если запустить Т2 в асинхронном режиме с внешним кварцем.

На STM32 видел реализацию просто на таймере, без доптактирования.

arduinec
Offline
Зарегистрирован: 01.09.2015

Yarik.Yar пишет:

Навскидку - частоту реально посчитать таймером, если запустить Т2 в асинхронном режиме с внешним кварцем.

Я полагаю, что все таймеры и счётчики в Ардуине зависимы от F_CPU. Если только внешний таймер подключать или часы реального времени, но это уже совсем другая история...

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Аппаратные таймеры атмеги не зависят от F_CPU. Они зависят от реальной тактовой частоты и настроек регистров.

__Alexander
Offline
Зарегистрирован: 24.10.2012

чет не догоню, если бы была иная частота, то в сериал вы бы видели мусор. если вы видите читаемый текст для платы на 16Мгц, то там действительно 16. 

__Alexander
Offline
Зарегистрирован: 24.10.2012

есть идея как измерить частоту. с помощью собаки, как известно она тактируется 1 Мгц, надо завести любой другой таймер, разрешить собаку (подобрав предделители для обоих) и разрешить прерывание от собаки. Ну и методом расчетов, зная предделители обеих высчитать частоту. если дать команду сброса, то должно выйти на продолжение программы без сброса МК.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

arduinec пишет:

Получается, что Ардуина сама не может определить свою частоту, а лишь руководствуется программно задаваемой F_CPU.

а, должна уметь?

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

а, если желается SysInfo, то достаточно считать сигнатуру чипа и фьюзы

arduinec
Offline
Зарегистрирован: 01.09.2015

Jeka_M пишет:

Аппаратные таймеры атмеги не зависят от F_CPU. Они зависят от реальной тактовой частоты и настроек регистров.

А откуда таймеры узнают с какой частотой они работают?

arduinec
Offline
Зарегистрирован: 01.09.2015

__Alexander пишет:

чет не догоню, если бы была иная частота, то в сериал вы бы видели мусор. если вы видите читаемый текст для платы на 16Мгц, то там действительно 16. 

В посте 9 указано, что скорость сериал-порта была уменьшена до 4800 (при 9600 был мусор).

arduinec
Offline
Зарегистрирован: 01.09.2015

__Alexander пишет:

есть идея как измерить частоту. с помощью собаки, как известно она тактируется 1 Мгц

А откуда она берёт частоту 1 МГц, если частота кварца неизвестна?

arduinec
Offline
Зарегистрирован: 01.09.2015

Клапауций 232 пишет:

а, если желается SysInfo, то достаточно считать сигнатуру чипа и фьюзы

Если Клапауций 232 приложит код, реализующий данную идею, то добавим его в скетч.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

arduinec пишет:

Если Клапауций 232 приложит код, реализующий данную идею, то добавим его в скетч.

внешним программатором фьюзы и сигнатура читается.

__Alexander
Offline
Зарегистрирован: 24.10.2012

arduinec пишет:

А откуда она берёт частоту 1 МГц, если частота кварца неизвестна?

На то он и сторожевой таймер, у него собственный рц генератор. Кстати, крапаль обманул, у 328-й собака работает от 128кГц.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

arduinec пишет:

А откуда таймеры узнают с какой частотой они работают?

А они и не знают, с какой частотой они работают. Им не нужно знать - они просто тикают с той тактовой частотой, которая поступает на вход предделителя таймера, а затем на сам таймер. 

Под фразой "Аппаратные таймеры атмеги не зависят от F_CPU" я имел в виду то, что в не зависимости от того, какое значение будет записано в F_CPU, частота тиканья таймера от этого не поменяется. Частота тиканья таймера может поменяться только в двух случаях: 1) Изменится тактовая частота, поступающая на вход предделителя таймера, 2) Изменится сам предделитель таймера (через настройки регистров).

То есть: если настроить таймер; включить прерывание от таймера; написать обработчик прерывания, в котором дергать ножку светодиода - то светодиод будет моргать всегда одинаково, в не зависимости от значения F_CPU.

arduinec
Offline
Зарегистрирован: 01.09.2015

Клапауций 232 пишет:

внешним программатором фьюзы и сигнатура читается.

Про внешний программатор я знаю. Надеялся, что Клапауций 232 знает какой-нибудь хитрый способ прочитать фьюзы в скетче.

arduinec
Offline
Зарегистрирован: 01.09.2015

Jeka_M пишет:

То есть: если настроить таймер; включить прерывание от таймера; написать обработчик прерывания, в котором дергать ножку светодиода - то светодиод будет моргать всегда одинаково, в не зависимости от значения F_CPU.

Остался вопрос: как с помощью таймеров определить частоту кварца Ардуины.
Функции Wiring типа micros() и delay() зависят от F_CPU - может это как-то использовать (ломаю голову).

__Alexander
Offline
Зарегистрирован: 24.10.2012

я же вроде отвечал, с помощью сторожевого таймера и одного из обычных.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

arduinec пишет:

Остался вопрос: как с помощью таймеров определить частоту кварца Ардуины.
Функции Wiring типа micros() и delay() зависят от F_CPU - может это как-то использовать (ломаю голову).

считать что-то таймером и пулять в сериал - последнее максимальное значение должно быть искомым числом пропорциональным частоте.

arduinec
Offline
Зарегистрирован: 01.09.2015

__Alexander пишет:

я же вроде отвечал, с помощью сторожевого таймера и одного из обычных.

Если __Alexander приложит код, реализующий данный способ определения частоты, то добавим его в скетч.

Мыслм вслух (по поводу обычных таймеров, с watchdog пока не экспериментировал):
Исходные параметры: кварц 16 МГц и F_CPU=16000000. Запускаем таймер на подсчёт частоты кварца. Делаем с помощью фунций Wiring задержку на 10 микросекунд и проверяем таймер. Он сосчитает до 160.
Меняем кварц на 8 МГц не меняя F_CPU=16000000. Таймер будет тикать в два раза медленнее, но функции Wiring не знают, что кварц поменялся. Поэтому задержка растянется до 20 мкс, и таймер сосчитает опять до 160.

 

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

arduinec пишет:
Если andriano приложит код, реализующий данный алгоритм, то добавим его в скетч.

arduinec пишет:
Если Клапауций 232 приложит код, реализующий данную идею, то добавим его в скетч.

arduinec пишет:
Если __Alexander приложит код, реализующий данный способ определения частоты, то добавим его в скетч.

Если arduinec расскажет, как часто он приобретает неопознанные девайсы...

__Alexander
Offline
Зарегистрирован: 24.10.2012

arduinec пишет:

Если __Alexander приложит код, реализующий данный способ определения частоты, то добавим его в скетч.

А авторские права? ))))))

Тут смотри в чем загвоздка, это надо делать первоначально и вычислить результат для всех взможных кварцев, потом уже, когда цифры будут известны, то настраивать уарт на 9600 при любом кварце, т.е. надо ввести таблицу.

зы. И еще, надо сначала выключить все таймеры, которые по умолчанию включает иде, и еще не факт что сериал заработает, надо будет работать напрямую с реистрами уарта.

arduinec
Offline
Зарегистрирован: 01.09.2015

Клапауций 232 пишет:

Если arduinec расскажет, как часто он приобретает неопознанные девайсы...

В нулевом посте написано, что девайсы мне удалось опознать. А уже потом появилась идея сделать совместными усилиями информационно-тестирующий скетч для Ардуино.

Кстати, код так никто и не выложил, в том числе и Клапауций 232.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

arduinec пишет:

Кстати, код так никто и не выложил, в том числе и Клапауций 232.

мои рекомендации не предусматривают прошивки контроллера каким либо кодом

разрешаю считывать фьюзы и сигнатуру с голого контроллера.

arduinec
Offline
Зарегистрирован: 01.09.2015

__Alexander пишет:

Тут смотри в чем загвоздка, это надо делать первоначально и вычислить результат для всех взможных кварцев, потом уже, когда цифры будут известны, то настраивать уарт на 9600 при любом кварце, т.е. надо ввести таблицу.

зы. И еще, надо сначала выключить все таймеры, которые по умолчанию включает иде, и еще не факт что сериал заработает, надо будет работать напрямую с реистрами уарта.

Я думал проще: запустить таймер watchdog и за определённое время посчитать количество импульсов кварца. Я сам с watchdog не работал, полез пока в документацию по нему.

__Alexander
Offline
Зарегистрирован: 24.10.2012

arduinec пишет:

Я думал проще: запустить таймер watchdog и за определённое время посчитать количество импульсов кварца. Я сам с watchdog не работал, полез пока в документацию по нему.

Ну по сути так и есть, запускаете ватчдог на нужное время и считатете сколько за это время протикал другой таймер и вычисляете. Я вроде так и сказал. Сложность в том, чтобы вывести в уарт читабельную информацию, надо сначала вычислить частоту, но ардуино иде такая кака, что если выключить все таймеры, то сериал ваш работать не будет. надо с нуля его инициализировать и выдавать информацию. Усекаете? У вас терминал работает на 9600, на разных кварцах у вас будет выводится всякий бред.

 

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

__Alexander пишет:

 У вас терминал работает на 9600, на разных кварцах у вас будет выводится всякий бред.

как вариант писать в EEPROM в лупе и считывать при инициализации - после первой перезагрузки будет актуальное значение.

только не очень часто писать. :D

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

ну, ок. предположим, мы определились с методами и написали код, который нужно залить в плату...

а, как? если 

__Alexander пишет:

У вас терминал работает на 9600, на разных кварцах у вас будет выводится всякий бред.

__Alexander
Offline
Зарегистрирован: 24.10.2012

Та не, зачем? Собака работет на одной и той же частоте (с поправкой на температуру и вольтаж), просто посидеть с полчасика и переписать значения для всех "стандартных частот" и всех "стандартных" скоростей уарта. Просто сделать табличку или просто сравнением:

if (TCNT1 > 56 && TCNT1 < 61) то частота кварца 16Мгц и UBRRL0 = 103.

if (TCNT1 > 25 && TCNT1 < 31) то частота кварца 8Мгц и UBRRL0 = 51.

И тогда вывод в уарт будет всегда читабельным.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

__Alexander пишет:

И тогда вывод в уарт будет всегда читабельным.

ок. и, как это туда воткнуть, если мы можем узнать скорость порта только после прошивки, а для прошивки нужно знать скорость порта.

это какая-то рекурсия.

__Alexander
Offline
Зарегистрирован: 24.10.2012

Клапауций 232 пишет:

ок. и, как это туда воткнуть, если мы можем узнать скорость порта только после прошивки, а для прошивки нужно знать скорость порта.

это какая-то рекурсия.

А за бутлодырь речи вроде как и не было, ясен пень, что заменив кварц на другой бут работать не будет.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

__Alexander пишет:

А за бутлодырь речи вроде как и не было, ясен пень, что заменив кварц на другой бут работать не будет.

тогда вообще не интересно - залить блинк с интервалом в 1 секунду и медитировать на результат.

__Alexander
Offline
Зарегистрирован: 24.10.2012

Клапауций 232 пишет:

тогда вообще не интересно - залить блинк с интервалом в 1 секунду и медитировать на результат.

Работал лет десят назад с бутом, который по длине стартового импульса настраивал скорость автоматом, в проге надо было просто указать порт. 

А с другой стороны, очень даже полезный способ отладки, особенно на расстоянии, перегрузился от неожиданности МК по собаке, а в прерывании от нее сохранили в эпром номер учаска кода... удобная штука.

arduinec
Offline
Зарегистрирован: 01.09.2015

__Alexander пишет:

Сложность в том, чтобы вывести в уарт читабельную информацию, надо сначала вычислить частоту, но ардуино иде такая кака, что если выключить все таймеры, то сериал ваш работать не будет. надо с нуля его инициализировать и выдавать информацию. Усекаете? У вас терминал работает на 9600, на разных кварцах у вас будет выводится всякий бред.

Если мы будем знать частоту кварца, то сможем и любые тайминги нужным образом выставить, в том числе и Serial.begin(). Кроме того, информацию можно выводить и на дисплей.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

arduinec пишет:

Если мы будем знать частоту кварца,

...то тему можно закрывать.

__Alexander
Offline
Зарегистрирован: 24.10.2012

Последний раз для особых оптимистов. Ардуино ИДЕ настраивает переферию как ей захочется, так отследить частоту невозможно, т.к. в прерывании одного из таймеров вызываются куча нахер ненужных функций. Работу таймеров надо запрещать. Но какого-то юха, запрет таймеров влияет на работу вашего Serial.begin(). Я хз. Может я не по русски пишу, но надо вместо Serial.begin() работать напрямую с регистрами, которые написаны в datasheet на МК. Может так понятнее станет.

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

http://dropmefiles.com/sYsZ5

 

а ну скажи число в терминале при 16мгц кварце.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

__Alexander пишет:

http://dropmefiles.com/sYsZ5

а ну скажи число в терминале при 16мгц кварце.

кто скажи и у кого возникнет желание что-то скачать с помойки?

__Alexander
Offline
Зарегистрирован: 24.10.2012

Клапауций 232 пишет:

кто скажи и у кого возникнет желание что-то скачать с помойки?

Та мне как-то насрать. Ну если что, то подскажи где крутые пацаны выкладывают файлики?

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

__Alexander пишет:

Та мне как-то насрать. Ну если что, то подскажи где крутые пацаны выкладывают файлики?

не важно где - важно описание и желательна прямая ссылка.

ну, как самый популярный www.dropbox.com

arduinec
Offline
Зарегистрирован: 01.09.2015

__Alexander пишет:

где крутые пацаны выкладывают файлики?

На yandex.ru вместе с почтовым ящиком бесплатно 10 Гб для хранения файлов дают.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

arduinec пишет:

Про внешний программатор я знаю. Надеялся, что Клапауций 232 знает какой-нибудь хитрый способ прочитать фьюзы в скетче.

 Для этого есть штатные дуиновские функции. Правда они нигде не описаны.. :) Кстати ещё в тему - есть способ, который без внешних девайсов позволит узнать тактовую частоту. Правда весьма примерно. Собака тактируется от своего независимого RC-генератора, можно запустить один из таймеров , на время, отсчитанное собакой, и посмотреть сколько насчитал таймер. По этим цифрам расситать частоту. Я даже скетч такой писал, правда назначение было другим -расчёт точности собаки. Но удобнее всего ткнуть осциллом в кварц и измерить. Если кварца нет, значит частота 8 или 1 Мгц :),  можно прочесть фузы и узнать.  Или ещё изящный вариант -включить фуз CKOUT и тактовая появиться на ноге PB0.

arduinec
Offline
Зарегистрирован: 01.09.2015

Добавил вывод фьюзов.
Версия 1.02

// SysInfo for Arduino
#define Version 1.02

#include <avr/boot.h>

void setup()
{
  Serial.begin(9600);

  Serial.print("SysInfo for Arduino version ");
  Serial.println(Version);
  Serial.println();

  VCC();
  Frequency();
  Fuses();
  TestPins();
}

void loop() {}

void VCC()
{
  #define Vref 1100
  int mvVcc;

  ADMUX = 1<<REFS0 | 0x0E;
  ADCSRA = (1<<ADEN) | (1<<ADATE) | (1<<ADSC) | 5;
  delay(1);
  mvVcc = (1023L * Vref) / ADC;

  Serial.print("VCC = ");
  Serial.print(mvVcc);
  Serial.println(" mV");
  Serial.println();
}

void Frequency()
{
  unsigned long ustime1, ustime2;
  int i, mhzFreq, iMax = 10000;

  Serial.print("F_CPU = ");
  Serial.println(F_CPU);

  ustime1 = micros();
  for(i=iMax; i>0; i--) __asm__("nop\n\t");
  ustime2 = micros();
  mhzFreq = 5 * (long)iMax / (ustime2 - ustime1) + 1;

  Serial.print("Frequency = ");
  Serial.print(mhzFreq);
  Serial.println(" MHz");
  Serial.println();
}

void Fuses()
{
  #define SIGRD 5

  Serial.print("Signatura = ");
  Serial.print(boot_signature_byte_get(0),HEX);
  Serial.print(boot_signature_byte_get(2),HEX);
  Serial.println(boot_signature_byte_get(4),HEX);

  Serial.print("Fuses (L/H/ext) = ");
  Serial.print(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS),HEX);
  Serial.print(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS),HEX);
  Serial.println(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS),HEX);

  Serial.println();
}

void TestPins()
{
  #define FIRST_PIN 0
  #define LAST_PIN 19

  Serial.println("Test of short circuit on GND or VCC:");

  for(byte pin = FIRST_PIN; pin <= LAST_PIN; pin++)
  {
    if(pin < 10) Serial.print("Pin:  ");
    else Serial.print("Pin: ");
    Serial.print(pin);

    pinMode(pin, OUTPUT);
    digitalWrite(pin, 0);
    Serial.print("    Low: ");
    if(!digitalRead(pin)) Serial.print("Ok  ");
    else Serial.print("Fail");

    digitalWrite(pin, 1);
    Serial.print("  High: ");
    if(digitalRead(pin)) Serial.print("Ok  ");
    else Serial.print("Fail");

    pinMode(pin, INPUT_PULLUP);
    Serial.print("  Pull Up: ");
    if(digitalRead(pin)) Serial.print("Ok  ");
    else Serial.print("Fail");

    Serial.println();
    pinMode(pin, INPUT);
  }
 
  Serial.println();
}