Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2f3a683

Browse files
Xaytonfacchinm
authored andcommitted
Make AddressChanger interactive
1 parent 10bda6d commit 2f3a683

File tree

1 file changed

+230
-34
lines changed

1 file changed

+230
-34
lines changed

‎examples/Utilities/AddressChanger/AddressChanger.ino‎

Lines changed: 230 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,60 +8,256 @@
88

99
#include "Wire.h"
1010

11-
// Setting new_address to 0 means that the module will get back its original address
12-
const uint8_t new_address = 0;
11+
struct DetectedModulino {
12+
uint8_t addr;
13+
String modulinoType;
14+
String pinstrap;
15+
String defaultAddr;
16+
};
17+
18+
#define MAX_DEVICES 16
19+
DetectedModulino rows[MAX_DEVICES];
20+
int numRows = 0;
1321

14-
uint8_t address;
1522

1623
void setup() {
1724
Wire1.begin();
1825
Serial.begin(115200);
19-
delay(1000);
20-
if (new_address != 0 && (new_address < 8 || new_address > 0x77)) {
21-
Serial.println("Address outside valid range");
22-
while (1);
26+
27+
delay(600);
28+
discoverDevices();
29+
}
30+
31+
bool waitingInput = false;
32+
void loop() {
33+
if (numRows == 0) return;
34+
if (Serial.available() == 0 && waitingInput) return;
35+
36+
if (Serial.available() > 0) {
37+
String hex1 = Serial.readStringUntil(' '); // Read until space (or other delimiter)
38+
String hex2 = Serial.readStringUntil('\n'); // Read until newline
39+
Serial.println("> " + hex1 + " " + hex2); // Print what the user inserted.
40+
41+
int num1 = parseHex(hex1); // Parse the first hex number
42+
int num2 = parseHex(hex2); // Parse the second hex number
43+
if (num1 == -1 || num2 == -1) {
44+
Serial.println("Error: Incomplete or invalid input. Please enter two hexadecimal numbers");
45+
return;
46+
}
47+
48+
bool success = updateI2cAddress(num1, num2);
49+
if (!success) return; // If the update failed, skip discovery and messages, and wait for input again.
50+
51+
discoverDevices();
52+
waitingInput = false;
53+
}
54+
55+
Serial.println("Enter the current address, space, and new address (ex. \"0x20 0x30\" or \"20 2A\"):");
56+
Serial.println(" - Enter \"<addr> 0\" to reset the device at <addr> to its default address.");
57+
Serial.println(" - Enter \"0 0\" to reset all devices to the default address.");
58+
waitingInput = true;
59+
}
60+
61+
// Updates the device at current address to new address. Supports broadcasting and setting default address (0).
62+
// Returns true if the update was successful, false otherwise.
63+
bool updateI2cAddress(int curAddress, int newAddress) {
64+
uint8_t data[40] = { 'C', 'F', newAddress * 2 };
65+
memset(data + 3, 0, sizeof(data) - 3); // Zero the rest of the buffer.
66+
67+
// Validate the current address, it must match a detected device.
68+
if (curAddress != 0 && !findRow(curAddress)) {
69+
Serial.println("Error: current address 0x" + String(curAddress, HEX) + " not found in the devices list\n");
70+
return false;
71+
}
72+
73+
if (curAddress != 0 && isFixedAddrDevice(curAddress)) {
74+
Serial.println("Error: address 0x" + String(curAddress, HEX) + " is a non configurable device\n");
75+
return false;
76+
}
77+
78+
// Validate the new address.
79+
if (newAddress != 0 && (newAddress < 8 || newAddress > 0x77)) {
80+
Serial.println("Error: new address 0x" + String(newAddress, HEX) + " must be from 0x08 to 0x77\n");
81+
return false;
82+
}
83+
84+
if (curAddress == 0) {
85+
Serial.print("Updating all devices (broadcast 0x00) to 0x" + String(newAddress, HEX));
86+
} else {
87+
Serial.print("Updating the device address from 0x" + String(curAddress, HEX) + " to 0x" + String(newAddress, HEX));
88+
}
89+
if (newAddress == 0) Serial.print(" (default address)");
90+
Serial.print("...");
91+
92+
Wire1.beginTransmission(curAddress);
93+
Wire1.write(data, 40);
94+
Wire1.endTransmission();
95+
96+
delay(500);
97+
98+
if (newAddress == 0) {
99+
Serial.println(" done\n");
100+
return true;
101+
} else {
102+
Wire1.requestFrom(newAddress, 1);
103+
if (Wire1.available()) {
104+
Serial.println(" done\n");
105+
return true;
106+
} else {
107+
Serial.println(" error\n");
108+
return false;
109+
}
110+
}
111+
}
112+
113+
// Function to parse hex number (with or without 0x prefix)
114+
int parseHex(String hexStr) {
115+
hexStr.trim();
116+
117+
if (hexStr.length() == 0) {
118+
return -1;
119+
}
120+
121+
if (hexStr.startsWith("0x") || hexStr.startsWith("0X")) {
122+
hexStr = hexStr.substring(2); // Remove the "0x" prefix
23123
}
24-
// Search for devices and wait for user confirmation
25-
for (int i = 8; i < 128; i++) {
26-
Wire1.beginTransmission(i);
27-
auto err = Wire1.endTransmission();
28-
if (err == 0) {
29-
Serial.print("Found device at ");
30-
Serial.println(i);
31-
address = i;
32-
Serial.println("Press 'c' to configure the new address");
124+
125+
// Validate that the remaining string contains only valid hexadecimal characters (0-9, A-F, a-f)
126+
for (int i = 0; i < hexStr.length(); i++) {
127+
if (!isHexDigit(hexStr.charAt(i))) {
128+
return -1;
129+
}
130+
}
131+
132+
return strtol(hexStr.c_str(), NULL, 16);
133+
}
134+
135+
bool isHexDigit(char c) {
136+
return ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'));
137+
}
138+
139+
void discoverDevices() {
140+
char buffer[64];
141+
Serial.println("ADDR\tMODULINO\tPINSTRAP\tDEFAULT ADDR"); // Table heading.
142+
143+
numRows = 0;
144+
145+
// Discover all modulino devices connected to the I2C bus.
146+
for (int addr = 8; addr < 128; addr++) {
147+
Wire1.beginTransmission(addr);
148+
if (Wire1.endTransmission() != 0) continue;
149+
150+
if (numRows >= MAX_DEVICES) {
151+
Serial.println("Too many devices connected, maximum supported is" + String(MAX_DEVICES));
152+
return;
153+
}
154+
155+
// Some addresses represent non configurable devices (no MCU on it). Handle them as a special case.
156+
if (isFixedAddrDevice(addr)) {
157+
snprintf(buffer, 64, "0x%02X (cannot change)", addr);
158+
addRow(addr, fixedAddrToName(addr), "-", String(buffer));
159+
160+
continue; // Stop here, do not try to communicate with this device.
33161
}
162+
163+
{
164+
uint8_t pinstrap = 0; // Variable to store the pinstrap (device type)
165+
Wire1.beginTransmission(addr); // Begin I2C transmission to the current address
166+
Wire1.write(0x00); // Send a request to the device (assuming 0x00 is the register for device type)
167+
Wire1.endTransmission(); // End transmission
168+
169+
delay(50); // Delay to allow for the device to respond
170+
171+
Wire1.requestFrom(addr, 1); // Request 1 byte from the device at the current address
172+
if (Wire1.available()) {
173+
pinstrap = Wire1.read(); // Read the device type (pinstrap)
174+
} else {
175+
// If an error happens in the range 0x78 to 0x7F, ignore it.
176+
if (addr >= 0x78) continue;
177+
Serial.println("Failed to read device type at address 0x" + String(addr, HEX));
178+
}
179+
180+
snprintf(buffer, 64, "0x%02X", pinstrap);
181+
auto hexPinstrap = String(buffer);
182+
183+
snprintf(buffer, 64, "0x%02X", pinstrap / 2); // Default address is half pinstrap.
184+
auto defaultAddr = String(buffer);
185+
if (addr != pinstrap / 2) defaultAddr += " *"; // Mark devices with modified address.
186+
187+
addRow(addr, pinstrapToName(pinstrap), hexPinstrap, defaultAddr);
188+
}
189+
}
190+
191+
// Print the results.
192+
for (int i = 0; i < numRows; i++) {
193+
char buffer[16];
194+
snprintf(buffer, 16, "0x%02X", rows[i].addr);
195+
196+
Serial.print(fixedWidth(buffer, 8));
197+
Serial.print(fixedWidth(rows[i].modulinoType, 16));
198+
Serial.print(fixedWidth(rows[i].pinstrap, 16));
199+
Serial.println(fixedWidth(rows[i].defaultAddr, 12));
34200
}
35201
}
36202

203+
void addRow(uint8_t address, String modulinoType, String pinstrap, String defaultAddr) {
204+
if (numRows >= MAX_DEVICES) return;
205+
206+
rows[numRows].addr = address;
207+
rows[numRows].modulinoType = modulinoType;
208+
rows[numRows].pinstrap = pinstrap;
209+
rows[numRows].defaultAddr = defaultAddr;
210+
numRows++; // Increment the row counter
211+
}
212+
213+
bool findRow(uint8_t address) {
214+
for (int i = 0; i < numRows; i++) {
215+
if (rows[i].addr == address) return true;
216+
}
217+
return false;
218+
}
219+
220+
221+
// Function to add padding to the right to ensure each field has a fixed width
222+
String fixedWidth(String str, int width) {
223+
for (int i = str.length(); i < width; i++) str += ' ';
224+
return str;
225+
}
226+
37227
String pinstrapToName(uint8_t pinstrap) {
38228
switch (pinstrap) {
39229
case 0x3C:
40-
return "BUZZER";
230+
return "Buzzer";
41231
case 0x7C:
42-
return "BUTTONS";
232+
return "Buttons";
43233
case 0x76:
44234
case 0x74:
45-
return "ENCODER";
235+
return "Encoder";
46236
case 0x6C:
47-
return "SMARTLEDS";
237+
return "Smartleds";
48238
}
49239
return "UNKNOWN";
50240
}
51241

52-
void loop() {
53-
// put your main code here, to run repeatedly:
54-
if (Serial.available()) {
55-
if (Serial.read() == 'c') {
56-
Serial.print("Assigning new address to ");
57-
Serial.println(address);
58-
uint8_t data[40] = { 'C', 'F', new_address * 2 };
59-
Wire1.beginTransmission(address);
60-
Wire1.write(data, 40);
61-
Wire1.endTransmission();
62-
delay(1000);
63-
Wire1.requestFrom(new_address, 1);
64-
Serial.println("Device type " + pinstrapToName(Wire1.read()) + " at new address " + String(new_address));
65-
}
242+
String fixedAddrToName(uint8_t address) {
243+
switch (address) {
244+
case 0x29:
245+
return "Distance";
246+
case 0x44:
247+
return "Thermo";
248+
case 0x6A:
249+
case 0x6B:
250+
return "Movement";
251+
}
252+
return "UNKNOWN";
253+
}
254+
255+
bool isFixedAddrDevice(uint8_t addr) {
256+
// List of non-configurable devices, recognized by their fixed I2C address.
257+
const uint8_t fixedAddr[] = { 0x29, 0x44, 0x6A, 0x6B };
258+
259+
for (int i = 0; i < sizeof(fixedAddr) / sizeof(fixedAddr[0]); i++) {
260+
if (addr == fixedAddr[i]) return true;
66261
}
262+
return false;
67263
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /