Как получить уникальный идентификатор для всех плат Arduino?

После того как вы загрузили скетч на одну из своих плат Arduino, трудно точно сказать, какой исходный код привел к этому скетчу.

Действительно, вы можете изменить исходный код своего скетча на своем ПК, не обновляя его (в двоичном формате) на своей плате.

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

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

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

Отсюда мой вопрос: как я могу получить уникальный идентификатор для платы Arduino?

Изменить:

Это мой текущий список плат (минимальный список, который должен поддерживаться подходом с одним уникальным идентификатором):

  • УНО R3
  • Мега 2560
  • Юн
  • Робот Arduino (должны быть две эквивалентные платы Leonardo)

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

, 👍29

Обсуждение

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


8 ответов


13

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

документация по EEPROM

Вы должны писать по определенному адресу, а затем будущие скетчи могут считывать идентификатор и делать с ним все, что угодно.


Вы также можете увидеть уникальный идентификатор или адрес на стороне хоста. Я недостаточно хорошо разбираюсь в USB-устройствах, чтобы рассказать вам больше, но чип, управляющий связью через USB, может иметь уникальный идентификатор, который вы могли бы использовать. Однако ваш код Arduino не сможет использовать это.

В качестве альтернативы можно просто использовать этикетировщик и наклеить этикетку на каждую плату.

,

Что касается уникального аспекта вопроса, [GUID](http://en.wikipedia.org/wiki/Globally_unique_identifier) может решить это (с небольшой погрешностью)., @Matthew G.

Первоначально я думал использовать для этого EEPROM; но это требует дополнительной работы для каждой платы: создать новый уникальный идентификатор, а затем записать его в EEPROM. Кроме того, могут быть несовместимости с библиотеками, которые используются в моих скетчах (которые могут писать по одному и тому же адресу EEPROM). Наконец, в моем контексте мне нужно было бы прочитать идентификатор с моего ПК, что более сложно. Уникальный идентификатор USB кажется более интересным для мне., @jfpoilpret

Согласно моему ответу, если вы хотите, чтобы это было универсальное решение (для большинства людей и широкого спектра плат), использование идентификатора USB означает, что люди, использующие кабели FTDI на платах без моста USB-> Serial, не будут в состоянии использовать вашу систему., @Cybergibbons


8

Некоторые платы при подключении к компьютеру публикуют свой серийный номер. Мой Arduino Uno R3 говорит

[16818.451423] usb 3-2: SerialNumber: 85235353137351E02242

Хотя я не уверен, насколько он уникален.

,

Все ли платы Arduino имеют такой номер? Было бы неплохо иметь список досок, на которых он есть (или нет)., @jfpoilpret

Глядя на мины, на базе 32у4 нет, а на 328 и SAM3X8E есть, @Federico Fissore


4

Насколько мне известно, все USB-чипы имеют уникальный серийный номер, по крайней мере, для FTDI-чипов. В Linux вы можете легко присвоить уникальные имена устройств, см. мой веб-сайт.

В остальном то, что вы описываете, является довольно простой формой управления версиями. Убедитесь, что ваши исходные файлы имеют номера версий. Чтобы идентифицировать вашу Arduino, вы можете сделать ее Serial.Print(); именем и версией кода во время setup();.

,

Да, контроль версий - это более или менее то, чего я хочу достичь; но установка версии в коде и изменение ее каждый раз при изменении кода не вариант (слишком легко забыть). В настоящее время я использую github для своих скетчей, но я хотел бы легко узнать, какая версия какого скетча в данный момент работает на одной плате., @jfpoilpret

Существует макрос для даты и времени компиляции __DATE__ и __TIME__. Так что, по крайней мере, вы можете автоматически сохранить эту информацию в своем .hex-файле @jfpoilpret., @jippie

Хорошо, я не подумал об этих макросах для управления версиями., @jfpoilpret


16

Для получения уникального идентификатора можно использовать несколько способов.

  1. Чипы FTDI имеют запрограммированный на них уникальный серийный номер. Насколько мне известно, к нему можно получить доступ только со стороны ПК.
  2. Некоторые чипы со встроенным USB (например, ATmega8U2/16U2/32U2) имеют уникальный идентификатор в данных подписи, обычно используемый для USB. Может быть легко доступен с обеих сторон соединения. Сюда входит ATmega16U2, который используется в качестве USB->последовательного моста Arduino Uno R3.
  3. Некоторые чипы со встроенным USB, но без уникального идентификатора в подписи, по-прежнему будут иметь уникальный идентификатор, запрограммированный в стеке USB (например, LUFA), который используется для загрузчика или DFU (обновление прошивки устройства).
  4. Есть много чипов с глобальными уникальными серийными идентификаторами, например, Microchip 11AA02E48, все датчиков Dallas 1-Wire (включая общий датчик температуры DS18B20) и других серийных EEPROMS. Я использовал их в производственном оборудовании, которое должно иметь уникальный MAC-адрес.
  5. Вы можете изменить стандартный загрузчик Optiboot (или любой другой загрузчик, который вы используете), чтобы он мог хранить и отвечать уникальным идентификатором.

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

Если ваше решение будет универсальным, я бы посоветовал не использовать идентификатор USB. У меня около 30 плат на базе Arduino, и только 5 из них имеют встроенное USB-оборудование. Все остальные для программирования требуют внешнего кабеля FTDI. Это означает, что все они будут иметь одинаковый идентификатор.

,

Что вы *делаете* с **30** досками?, @asheeshr

В основном для беспроводных сенсорных сетей. У меня всего несколько настоящих Arduino — Duemilanova, Seeeduino Mega и Uno. Все остальные — это Teensy, Jeenodes, WiNodes, Nanodes и RFus., @Cybergibbons

+1 за подробный список возможных вариантов, спасибо! Я бы предпочел избегать 4, поскольку я не хочу добавлять определенное оборудование на все свои платы. 5. выглядит опасно (легко загрузить один и тот же модифицированный загрузчик на 2 разные платы) и громоздко (необходимо иметь разные исходные коды загрузчиков для загрузки на каждую плату). Пока что USB ID и FTDI кажутся неплохими решениями, но работают ли они со всеми моими текущими платами?, @jfpoilpret

Есть ли у Arduino глобально уникальные серийные идентификаторы? Как это прочитать?, @lanse7pty


2

Я сомневаюсь, что интерфейс USB на Uno дает вам уникальный серийный номер. Любое число будет частью кода, загруженного в чип, который, таким образом, будет одинаковым для нескольких устройств Uno.

Одним из подходов является чип DS2401 "Silicon Serial Number", который использует однопроводной интерфейс. Для этого потребуется только один свободный контакт и некоторый код (возможно, проблема будет в коде).

Наименее навязчивым и, вероятно, самым надежным методом будет просто прочитать код и проверить его сумму. Это именно то, что я делаю со своим детектором подписи чипа. Однако это обнаруживает только (как написано в настоящее время) подпись загрузчика. Довольно незначительное изменение, и оно может суммировать весь код скетча с помощью MD5.

Пример вывода:

Signature detector.
Written by Nick Gammon.
Signature = 1E  95  0F 
Fuses
Low = FF High = D6 Ext = FF Lock = CF

Processor = ATmega328P
Flash memory size = 32768
Bootloader in use: Yes
EEPROM preserved through erase: Yes
Watchdog timer always on: No
Bootloader is 512 bytes starting at 7E00

Bootloader:

7E00: 02 01 02 03 0405 06 07 08 09 0A 0B 0C 0D 0E 0F 
7E10: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7E20: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7E30: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
...
7FB0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7FC0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7FD0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7FE0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7FF0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 

MD5 sum of bootloader = 56 72 75 2D 5D B5 0D BA 25 10 DF BE 87 D2 A1 27 

Эта сумма MD5 (последняя строка) фактически является сигнатурой этого конкретного загрузчика. На самом деле самая последняя версия ищет их в таблице:

MD5 sum of bootloader = FB F4 9B 7B 59 73 7F 65 E8 D0 F8 A5 08 12 E7 9F 
Bootloader name: optiboot_atmega328

Итак, вы можете при загрузке скетча сгенерировать сумму MD5 шестнадцатеричного кода. Есть довольно простые способы сделать это. Затем вы можете выполнить операцию «git tag» в исходном коде, а затем (используя какой-либо автоматизированный или ручной процесс) вспомнить, что конкретная сумма MD5 шестнадцатеричного кода представляет код скетча в определенный момент.

Какая-то база данных, например:

Chip: Uno
MD5 sum: D8 8C 70 6D FE 1F DC 38 82 1E CE AE 23 B2 E6 E7 
Sketch: My_robot_sketch_42.ino
Git tag: version666

Теперь, чтобы найти источник с платы, вы устанавливаете сумму кода MD5 (путем считывания ее с платы), а затем ищете ее в своей базе данных.

,

1

Я подключил датчик температуры с одним проводом, каждый из которых имеет уникальный I'd. Все скетчи читали I'd при загрузке и записывали адрес при каждом последовательном соединении. Я сделал щит со всем необходимым оборудованием, поэтому, если бы мне нужно было перейти с Uno на Mega, устройство сохранило бы свою уникальность.

,

1

Существует крошечная библиотека для чтения и записи пользовательского идентификатора оборудования в EEPROM. Вы можете использовать его, чтобы избежать отправки неправильного скетча на Arduino или для идентификации устройства для других целей.

https://github.com/skoumalcz/arduino-id-guard

Отказ от ответственности: я являюсь автором библиотеки :-)

,

0
#include <avr/boot.h>
#ifdef __AVR_ATmega2560__  /// проверить, используется ли MEGA2560
#define USEMEGA_ID         ///
void setup()
{
#ifdef __AVR_ATmega2560__
  cli();
  int data3, data4;
  data3 = boot_signature_byte_get(0x04) * 256;
  data4 = boot_signature_byte_get(0x01);
  sei();
  MegaID = data3 + data4;
#endif
Serial.begin(115200);
  Serial.print("MegaID             \t: "); Serial.println(MegaID);
}

// Это покажет вам 3-значный MegaID
// Теперь вы можете создавать разные настройки для разных MEGA2560 с одним и тем же исходным кодом
,

Число, возвращаемое этим кодом, по-видимому, основано как на сигнатуре устройства (одинаковой для всех устройств ATmega2560), так и на заводском байте калибровки генератора (который может различаться между платами). Уникальность не гарантируется. Интересно, каков типичный разброс калибровочных байтов: это обусловливает вероятность коллизий идентификаторов., @Edgar Bonet

правильно!Там всего 3 номера. так что они 999 возможностей. это не много и не безопасно, но практично, когда у вас всего несколько плат, и вы хотите иметь разные настройки с одним и тем же кодом., @ESP Blynk