Как получить уникальный идентификатор для всех плат Arduino?
После того как вы загрузили скетч на одну из своих плат Arduino, трудно точно сказать, какой исходный код привел к этому скетчу.
Действительно, вы можете изменить исходный код своего скетча на своем ПК, не обновляя его (в двоичном формате) на своей плате.
У меня возникла идея создать своего рода "репозиторий скетчей", который будет заполняться, как только я загружу скетч на одну из своих плат. Затем я мог бы позже получить исходный код скетча, работающего на любой из моих плат.
Для такого репозитория мне сначала понадобится "индекс", который позволит мне узнать, с какой платой связан исходный код скетча.
Как правило, такой индекс должен быть уникальным для каждой платы Arduino.
Отсюда мой вопрос: как я могу получить уникальный идентификатор для платы Arduino?
Изменить:
Это мой текущий список плат (минимальный список, который должен поддерживаться подходом с одним уникальным идентификатором):
- УНО R3
- Мега 2560
- Юн
- Робот Arduino (должны быть две эквивалентные платы Leonardo)
В будущем я также могу создавать свои собственные платы (эквивалентные Uno, но базовые, без FTDI), поэтому, если подход также поддерживает их, это было бы лучше.
@jfpoilpret, 👍29
Обсуждение8 ответов
Насколько я знаю, чип не имеет какого-либо уникального идентификатора... но вы можете запрограммировать его в 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
Некоторые платы при подключении к компьютеру публикуют свой серийный номер. Мой Arduino Uno R3 говорит
[16818.451423] usb 3-2: SerialNumber: 85235353137351E02242
Хотя я не уверен, насколько он уникален.
Все ли платы Arduino имеют такой номер? Было бы неплохо иметь список досок, на которых он есть (или нет)., @jfpoilpret
Глядя на мины, на базе 32у4 нет, а на 328 и SAM3X8E есть, @Federico Fissore
Насколько мне известно, все USB-чипы имеют уникальный серийный номер, по крайней мере, для FTDI-чипов. В Linux вы можете легко присвоить уникальные имена устройств, см. мой веб-сайт.
В остальном то, что вы описываете, является довольно простой формой управления версиями. Убедитесь, что ваши исходные файлы имеют номера версий. Чтобы идентифицировать вашу Arduino, вы можете сделать ее Serial.Print();
именем и версией кода во время setup();
.
Да, контроль версий - это более или менее то, чего я хочу достичь; но установка версии в коде и изменение ее каждый раз при изменении кода не вариант (слишком легко забыть). В настоящее время я использую github для своих скетчей, но я хотел бы легко узнать, какая версия какого скетча в данный момент работает на одной плате., @jfpoilpret
Существует макрос для даты и времени компиляции __DATE__
и __TIME__
. Так что, по крайней мере, вы можете автоматически сохранить эту информацию в своем .hex-файле @jfpoilpret., @jippie
Хорошо, я не подумал об этих макросах для управления версиями., @jfpoilpret
Для получения уникального идентификатора можно использовать несколько способов.
- Чипы FTDI имеют запрограммированный на них уникальный серийный номер. Насколько мне известно, к нему можно получить доступ только со стороны ПК.
- Некоторые чипы со встроенным USB (например, ATmega8U2/16U2/32U2) имеют уникальный идентификатор в данных подписи, обычно используемый для USB. Может быть легко доступен с обеих сторон соединения. Сюда входит ATmega16U2, который используется в качестве USB->последовательного моста Arduino Uno R3.
- Некоторые чипы со встроенным USB, но без уникального идентификатора в подписи, по-прежнему будут иметь уникальный идентификатор, запрограммированный в стеке USB (например, LUFA), который используется для загрузчика или DFU (обновление прошивки устройства).
- Есть много чипов с глобальными уникальными серийными идентификаторами, например, Microchip 11AA02E48, все датчиков Dallas 1-Wire (включая общий датчик температуры DS18B20) и других серийных EEPROMS. Я использовал их в производственном оборудовании, которое должно иметь уникальный MAC-адрес.
- Вы можете изменить стандартный загрузчик 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
Я сомневаюсь, что интерфейс 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 (путем считывания ее с платы), а затем ищете ее в своей базе данных.
Я подключил датчик температуры с одним проводом, каждый из которых имеет уникальный I'd. Все скетчи читали I'd при загрузке и записывали адрес при каждом последовательном соединении. Я сделал щит со всем необходимым оборудованием, поэтому, если бы мне нужно было перейти с Uno на Mega, устройство сохранило бы свою уникальность.
Существует крошечная библиотека для чтения и записи пользовательского идентификатора оборудования в EEPROM. Вы можете использовать его, чтобы избежать отправки неправильного скетча на Arduino или для идентификации устройства для других целей.
https://github.com/skoumalcz/arduino-id-guard
Отказ от ответственности: я являюсь автором библиотеки :-)
#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
- Как использовать SPI на Arduino?
- Как сбросить или отформатировать Arduino?
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как сделать повторитель Wi-Fi на Arduino?
- Как очистить буфер FIFO на MPU6050?
- Элегантное решение для обновления содержимого TFT-дисплея
- Считывание нескольких поворотных энкодеров
- Что выбрать между датчиками температуры и влажности: AM230x или DHT22?
@jfpoilpret ... только что увидел этот пост во время просмотра сайта ... вы нашли решение или лучший вариант того, как это реализовать?, @dinotom