Arduino Yún Yún First Configuration

Connect your Yun product to the WiFi networks in a breeze using the Serial Monitor and answering a few simple questions within it.

This example shows you how to connect to a WiFi network with your Yún device using the Serial Monitor as the communication interface during the whole process.

Upload the sketch on your Yún device and open the Serial Monitor. The Serial Monitor output will display the available WiFi networks, then asks you to choose the one to use. You have to input the network password and then you are asked to give your Yún device a name and a password. If the connection with the selected network is successful, you get a confirmation message and the IP assigned to your Yún device. By pasting this IP address on your web browser you will be able to reach the Yún Panel for further options.

If something goes wrong, you can restart the procedure; if the network you want to connect to is not in the list, you may proceed with the manual selection specifying the network SSID and passkey.

Note: this sketch requires that your Yún device is running on firmware version 1.6.2 or newer. Please check the upgrade tutorial and be sure you're running the latest version available.

Hardware Required

  • Yún board or shield

  • a wireless network connected to the internet

Circuit

There is no circuit for this example.

The circuit for this tutorial.
The circuit for this tutorial.

image developed using Fritzing. For more circuit examples, see the Fritzing project page

Software Essentials

Libraries

Process.h is used to launch processes on the Linux processor, and other things like shell scripts. Here we use it to get the list of APs and to perform other actions that let us know the WiFi parameters.

Functions

String getUserInput(String out, bool obfuscated) - manages the input from the user through the Serial Monitor, printing back in the window. The boolean variable "obfuscated" is used to print out "*" when a password is entered.

void wifiConfig(String yunName, String yunPsw, String wifissid, String wifipsw, String wifiAPname, String countryCode, String encryption) - uses Process to execute a series of commands and scripts, under linux, that set the WiFi and network parameters as chosen by the user.

void startSerialTerminal() - simply initialize the two serial ports needed to perform the actions required by the sketch.

void loopSerialTerminal() - creates the connection between the two serial ports, one talking with the PC using USB, the other talking to the linux processor. It has a command mode that can be invoked typing '~' that shuts down Bridge and allows to set a different communication speed with the Atheros chip.

Usage

This sketch uses the Serial Monitor of your Arduino Software (IDE) to interact with you, asking the relevant information for the configuration. The Yún device uses the hardware serial port on pins 0 and 1 to communicate with the board, therefore this sketch requires a second hardware serial port to work properly. Please get ready with SSID (the Access Point name) and the key or passphrase to access the WiFi network. Load the sketch and then open the Serial Monitor clicking on the Magnifier Lens icon on the right of the icon bar. You will see a message as the one in the screenshot below.

Setup window one.
Setup window one.

The blue LED on the shield will start to blink after a while; when the scanning process is over, the sketch will offer all the available APs in a numbered list. The time required to scan the network depends on the number of APs and their signal strength. You choose the AP to use typing in the input field the corresponding number. Please remember to enable "NL" in the Serial Monitor as End of Line.

Setup window two.
Setup window two.

The selection of the AP triggers the connection process and the Yún device will sense if the network is open or protected. In this later case, you will be asked to provide the key. The Yún device needs to be named and protected with a password to allow easy and secure connections. Following these step, your device is ready to connect to the WiFi network, switching off the AP mode and initiating the access to the selected WiFi network. At the end of this process, the sketch will show the IP address obtained from the WiFi DHCP server.

Setup window three.
Setup window three.

If the connection fails, the sketch will report it and suggest to restart the whole procedure with a reset of your Yún device.

Code

The complete sketch is below :

1/*
2
3 Arduino Yún First configuration sketch
4
5 Configures the YunShield/Yún WiFi and infos via the Bridge
6
7 Works correctly if Line Ending is set as "NewLine"
8
9 If your board has two USB ports, use the Native one
10
11 The circuit:
12
13 Arduino YunShield
14
15 (or any Yun model with firmware > 1.6.1)
16
17 created March 2016
18
19 by Arduino LLC
20
21 This example code is in the public domain.
22
23 http://www.arduino.cc/en/Tutorial/YunFirstConfig
24
25*/
26
27#include <Process.h>
28
29#define MAX_WIFI_LIST 10
30
31String networks[MAX_WIFI_LIST];
32
33String yunName;
34
35String yunPassword;
36
37void setup() {
38
39 SERIAL_PORT_USBVIRTUAL.begin(9600); // initialize serial communication
40
41 while (!SERIAL_PORT_USBVIRTUAL); // do nothing until the serial monitor is opened
42
43 SERIAL_PORT_USBVIRTUAL.println(F("Hi! Nice to see you!"));
44
45 SERIAL_PORT_USBVIRTUAL.println(F("I'm your Yun assistant sketch"));
46
47 SERIAL_PORT_USBVIRTUAL.println(F("I'll help you configuring your Yun in a matter of minutes"));
48
49 SERIAL_PORT_USBVIRTUAL.println(F("Let's start by communicating with the Linux processor"));
50
51 SERIAL_PORT_USBVIRTUAL.println(F("When LED (L13) will light up we'll be ready to go!"));
52
53 SERIAL_PORT_USBVIRTUAL.println(F("Waiting..."));
54
55 SERIAL_PORT_USBVIRTUAL.println(F("(in the meanwhile, if you are using the IDE's serial monitor, make sure that it's configured to send a \"Newline\")\n"));
56
57 pinMode(13, OUTPUT);
58
59 digitalWrite(13, LOW);
60
61 Bridge.begin(); // make contact with the linux processor
62
63 digitalWrite(13, HIGH); // Led on pin 13 turns on when the bridge is ready
64
65 // Recover if the board is in AP mode - unused
66
67 Process wifiList;
68
69 bool controller = false;
70
71 wifiList.runShellCommand(F("iwinfo | grep \"Mode: Controller\""));
72
73 while (wifiList.available() > 0) {
74
75 wifiList.read();
76
77 controller = true;
78
79 }
80
81 // Get the list of reachable networks
82
83 wifiList.runShellCommand(F("iwinfo wlan0 scan | grep ESSID | cut -d\"\\\"\" -f2"));
84
85 uint8_t num_networks = 0;
86
87 uint8_t i = 0;
88
89 char c;
90
91 bool dropNet = false;
92
93 networks[0].reserve(32);
94
95 while (wifiList.available() > 0 && i < MAX_WIFI_LIST) {
96
97 c = wifiList.read();
98
99 if (c != '\n') {
100
101 networks[i] += c;
102
103 } else {
104
105 // check if we already found networks[i] and eventually drop it
106
107 for (uint8_t s = 0; s < i; s++) {
108
109 if (networks[i].equals(networks[s])) {
110
111 dropNet = true;
112
113 }
114
115 }
116
117 if (networks[i].c_str()[0] == ' ') {
118
119 dropNet = true;
120
121 }
122
123 if (i < MAX_WIFI_LIST && dropNet == false) {
124
125 networks[i++].reserve(32);
126
127 } else {
128
129 dropNet = false;
130
131 networks[i] = "";
132
133 }
134
135 }
136
137 }
138
139 num_networks = i;
140
141 String encryption;
142
143 String password;
144
145 int chose = 0;
146
147 // If networks number is 0, start manual configuration
148
149 if (num_networks == 0) {
150
151 SERIAL_PORT_USBVIRTUAL.println(F("Oops, it seems that you have no WiFi network available"));
152
153 SERIAL_PORT_USBVIRTUAL.println(F("Let's configure it manually"));
154
155 SERIAL_PORT_USBVIRTUAL.println(F("SSID of the network you want to connect to: "));
156
157 networks[0] = getUserInput(networks[0], false);
158
159 SERIAL_PORT_USBVIRTUAL.println(F("Password for the network you want to connect to: "));
160
161 password = getUserInput(password, true);
162
163 SERIAL_PORT_USBVIRTUAL.print(F("Encryption (eg WPA, WPA2, WEP): "));
164
165 encryption = getUserInput(encryption, false);
166
167 } else {
168
169 // else print them prepending a number
170
171 SERIAL_PORT_USBVIRTUAL.print(F("It looks like you have "));
172
173 SERIAL_PORT_USBVIRTUAL.print(num_networks);
174
175 SERIAL_PORT_USBVIRTUAL.println(F(" networks around you "));
176
177 SERIAL_PORT_USBVIRTUAL.println(F("Which one do you want to connect to?\n"));
178
179 for (i = 0; i < num_networks && i < MAX_WIFI_LIST; i++) {
180
181 SERIAL_PORT_USBVIRTUAL.print(i);
182
183 SERIAL_PORT_USBVIRTUAL.println(") " + networks[i]);
184
185 }
186
187 String selection;
188
189 selection = getUserInput(selection, false);
190
191 chose = atoi(selection.c_str());
192
193 }
194
195 // Extract the selected network security
196
197 bool openNet = false;
198
199 wifiList.runShellCommand("iwinfo wlan0 scan | grep \"" + networks[chose] + "\" -A5 | grep Encryption | cut -f2 -d\":\"");
200
201 while (wifiList.available() > 0) {
202
203 c = wifiList.read();
204
205 encryption += c;
206
207 }
208
209 if (encryption.indexOf("none") >= 0) {
210
211 openNet = true;
212
213 encryption = "none";
214
215 }
216
217 if (encryption.indexOf("WPA2") >= 0) {
218
219 encryption = "psk2";
220
221 }
222
223 if (encryption.indexOf("WPA") >= 0) {
224
225 encryption = "psk";
226
227 }
228
229 if (encryption.indexOf("WEP") >= 0) {
230
231 encryption = "wep";
232
233 }
234
235 if (openNet == false && password.length() == 0) {
236
237 SERIAL_PORT_USBVIRTUAL.print(F("It looks like you need a password to connect to "));
238
239 SERIAL_PORT_USBVIRTUAL.println(networks[chose]);
240
241 SERIAL_PORT_USBVIRTUAL.print(F("Write it here: "));
242
243 password = getUserInput(password, true);
244
245 }
246
247 // Change hostname/root password
248
249 SERIAL_PORT_USBVIRTUAL.println(F("We are almost done! Give a name and a password to your Yun"));
250
251 SERIAL_PORT_USBVIRTUAL.print(F("Name: "));
252
253 yunName = getUserInput(yunName, false);
254
255 SERIAL_PORT_USBVIRTUAL.print(F("Password: "));
256
257 yunPassword = getUserInput(yunPassword, true);
258
259 // Select a country code
260
261 String countryCode;
262
263 SERIAL_PORT_USBVIRTUAL.println(F("One last question: where do you live?"));
264
265 SERIAL_PORT_USBVIRTUAL.print(F("Insert a two letters county code (eg IT, US, DE): "));
266
267 countryCode = getUserInput(countryCode, false);
268
269 yunName.trim();
270
271 yunPassword.trim();
272
273 networks[chose].trim();
274
275 password.trim();
276
277 countryCode.trim();
278
279 // Configure the Yun with user provided strings
280
281 wifiConfig(yunName, yunPassword, networks[chose], password, "YUN" + yunName + "AP", countryCode, encryption);
282
283 SERIAL_PORT_USBVIRTUAL.print(F("Waiting for the Yun to connect to the network"));
284}
285
286bool Connected = false;
287
288bool serialTerminalMode = false;
289int runs = 0;
290
291void loop() {
292
293 if (!serialTerminalMode) {
294
295 String resultStr = "";
296
297 if (!Connected) {
298
299 SERIAL_PORT_USBVIRTUAL.print(".");
300
301 runs++;
302
303 }
304
305 // If it takes more than 20 seconds to connect, stop trying
306
307 if (runs > 20) {
308
309 SERIAL_PORT_USBVIRTUAL.println("");
310
311 SERIAL_PORT_USBVIRTUAL.println(F("We couldn't connect to the network."));
312
313 SERIAL_PORT_USBVIRTUAL.println(F("Restart the board if you want to execute the wizard again"));
314
315 resultStr = getUserInput(resultStr, false);
316
317 }
318
319 // Check if we have an IP address
320
321 Process wifiCheck;
322
323 wifiCheck.runShellCommand(F("/usr/bin/pretty-wifi-info.lua | grep \"IP address\" | cut -f2 -d\":\" | cut -f1 -d\"/\"" )); // command you want to run
324
325 while (wifiCheck.available() > 0) {
326
327 char c = wifiCheck.read();
328
329 resultStr += c;
330
331 }
332
333 delay(1000);
334
335 if (resultStr != "") {
336
337 // We got an IP, freeze the loop, display the value and "spawn" a serial terminal
338
339 Connected = true;
340
341 resultStr.trim();
342
343 SERIAL_PORT_USBVIRTUAL.println("");
344
345 SERIAL_PORT_USBVIRTUAL.print(F("\nGreat! You can now reach your Yun from a browser typing http://"));
346
347 SERIAL_PORT_USBVIRTUAL.println(resultStr);
348
349 SERIAL_PORT_USBVIRTUAL.print(F("Press 'Enter' key twice to start a serial terminal"));
350
351 resultStr = getUserInput(resultStr, false);
352
353 serialTerminalMode = true;
354
355 //startSerialTerminal();
356
357 SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command
358
359 delay(100);
360
361 SERIAL_PORT_HARDWARE.println("\nreset\n\n");
362
363 SERIAL_PORT_HARDWARE.flush();
364
365 SERIAL_PORT_HARDWARE.println("\nreset\n\n");
366
367 SERIAL_PORT_HARDWARE.write((uint8_t *)"\n", 1);
368
369 // discard all stuff for 2 seconds
370
371 long start = millis();
372
373 while (millis() - start < 2000) {
374
375 if (SERIAL_PORT_HARDWARE.available()) {
376
377 SERIAL_PORT_HARDWARE.read();
378
379 }
380
381 }
382
383 }
384
385 } else {
386
387 loopSerialTerminal();
388
389 }
390}
391
392String getUserInput(String out, bool obfuscated) {
393
394 /*
395
396 while (SerialUSB.available() <= 0) {}
397
398 while (SerialUSB.available() > 0) {
399
400 char c = SerialUSB.read();
401
402 out += c;
403
404 }
405
406 return out;
407
408 */
409
410 while (SERIAL_PORT_USBVIRTUAL.available() <= 0) {}
411
412 while (1) {
413
414 char c = SERIAL_PORT_USBVIRTUAL.read();
415
416 char next = SERIAL_PORT_USBVIRTUAL.peek();
417
418 if (c == '\n' || c == '\r') {
419
420 if (next == '\n') {
421
422 // discard it
423
424 SERIAL_PORT_USBVIRTUAL.read();
425
426 }
427
428 break;
429
430 }
431
432 else {
433
434 if (c != -1) {
435
436 out += c;
437
438 if (obfuscated)
439
440 SERIAL_PORT_USBVIRTUAL.print("*");
441
442 else
443
444 SERIAL_PORT_USBVIRTUAL.print(c);
445
446 }
447
448 }
449
450 }
451
452 SERIAL_PORT_USBVIRTUAL.println("");
453
454 return out;
455}
456
457void wifiConfig(String yunName, String yunPsw, String wifissid, String wifipsw, String wifiAPname, String countryCode, String encryption) {
458
459 Process p;
460
461 p.runShellCommand("blink-start 100"); //start the blue blink
462
463 p.runShellCommand("hostname " + yunName); //change the current hostname
464
465 p.runShellCommand("uci set system.@system[0].hostname='" + yunName + "'"); //change teh hostname in uci
466
467 p.runShellCommand("uci set arduino.@arduino[0].access_point_wifi_name='" + wifiAPname + "'");
468
469 //this block resets the wifi psw
470
471 p.runShellCommand("uci set wireless.@wifi-iface[0].encryption='" + encryption + "'");
472
473 p.runShellCommand("uci set wireless.@wifi-iface[0].mode='sta'\n");
474
475 p.runShellCommand("uci set wireless.@wifi-iface[0].ssid='" + wifissid + "'");
476
477 p.runShellCommand("uci set wireless.@wifi-iface[0].key='" + wifipsw + "'");
478
479 p.runShellCommand("uci set wireless.radio0.channel='auto'");
480
481 p.runShellCommand("uci set wireless.radio0.country='" + countryCode + "'");
482
483 p.runShellCommand("uci delete network.lan.ipaddr");
484
485 p.runShellCommand("uci delete network.lan.netmask");
486
487 p.runShellCommand("uci set network.lan.proto='dhcp'");
488
489 p.runShellCommand("echo -e \"" + yunPsw + "\n" + yunPsw + "\" | passwd root"); //change the passwors
490
491 p.runShellCommand("uci commit"); //save the mods done via UCI
492
493 p.runShellCommand("blink-stop"); //start the blue blink
494
495 p.runShellCommand("wifi ");
496}
497
498long linuxBaud = 250000;
499
500void startSerialTerminal() {
501
502 SERIAL_PORT_USBVIRTUAL.begin(115200); // open serial connection via USB-Serial
503
504 SERIAL_PORT_HARDWARE.begin(linuxBaud); // open serial connection to Linux
505}
506
507bool commandMode = false;
508void loopSerialTerminal() {
509
510 // copy from USB-CDC to UART
511
512 int c = SERIAL_PORT_USBVIRTUAL.read(); // read from USB-CDC
513
514 if (c != -1) { // got anything?
515
516 if (commandMode == false) { // if we aren't in command mode...
517
518 if (c == '~') { // Tilde '~' key pressed?
519
520 commandMode = true; // enter in command mode
521
522 } else {
523
524 SERIAL_PORT_HARDWARE.write(c); // otherwise write char to UART
525
526 }
527
528 } else { // if we are in command mode...
529
530 if (c == '0') { // '0' key pressed?
531
532 SERIAL_PORT_HARDWARE.begin(57600); // set speed to 57600
533
534 SERIAL_PORT_USBVIRTUAL.println("Speed set to 57600");
535
536 } else if (c == '1') { // '1' key pressed?
537
538 SERIAL_PORT_HARDWARE.begin(115200); // set speed to 115200
539
540 SERIAL_PORT_USBVIRTUAL.println("Speed set to 115200");
541
542 } else if (c == '2') { // '2' key pressed?
543
544 SERIAL_PORT_HARDWARE.begin(250000); // set speed to 250000
545
546 SERIAL_PORT_USBVIRTUAL.println("Speed set to 250000");
547
548 } else if (c == '3') { // '3' key pressed?
549
550 SERIAL_PORT_HARDWARE.begin(500000); // set speed to 500000
551
552 SERIAL_PORT_USBVIRTUAL.println("Speed set to 500000");
553
554 } else if (c == '~') { // '~` key pressed?
555
556 SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command
557
558 SERIAL_PORT_USBVIRTUAL.println("Sending bridge's shutdown command");
559
560 } else { // any other key pressed?
561
562 SERIAL_PORT_HARDWARE.write('~'); // write '~' to UART
563
564 SERIAL_PORT_HARDWARE.write(c); // write char to UART
565
566 }
567
568 commandMode = false; // in all cases exit from command mode
569
570 }
571
572 }
573
574 // copy from UART to USB-CDC
575
576 c = SERIAL_PORT_HARDWARE.read(); // read from UART
577
578 if (c != -1) { // got anything?
579
580 SERIAL_PORT_USBVIRTUAL.write(c); // write to USB-CDC
581
582 }
583}

Last revision 2016/05/25 by SM

Contribute to Arduino

Join the community and suggest improvements to this article via GitHub. Make sure to read out contribution policy before making your pull request.

Missing something?

Check out our store and get what you need to follow this tutorial.