Arduino Yún Yún First Configuration
Connect your Yun product to the Wi-Fi 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 Wi-Fi 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 Wi-Fi 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.
  
    
    
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 Wi-Fi 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 Wi-Fi 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 Wi-Fi 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.
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.
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 Wi-Fi network, switching off the AP mode and initiating the access to the selected Wi-Fi network. At the end of this process, the sketch will show the IP address obtained from the Wi-Fi DHCP server.
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 sketch4
5  Configures the YunShield/Yún WiFi and infos via the Bridge6
7  Works correctly if Line Ending is set as "NewLine"8
9  If your board has two USB ports, use the Native one10
11  The circuit:12
13   Arduino YunShield14
15   (or any Yun model with firmware > 1.6.1)16
17  created March 201618
19  by Arduino LLC20
21  This example code is in the public domain.22
23  http://www.arduino.cc/en/Tutorial/YunFirstConfig24
25*/26
27#include <Process.h>28
29#define MAX_WIFI_LIST 1030
31String networks[MAX_WIFI_LIST];32
33String yunName;34
35String yunPassword;36
37void setup() {38
39  SERIAL_PORT_USBVIRTUAL.begin(9600);  // initialize serial communication40
41  while (!SERIAL_PORT_USBVIRTUAL);     // do nothing until the serial monitor is opened42
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 processor62
63  digitalWrite(13, HIGH);  // Led on pin 13 turns on when the bridge is ready64
65  // Recover if the board is in AP mode - unused66
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 networks82
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 it106
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 configuration148
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 number170
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 security196
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 password248
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 code260
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 strings280
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 trying306
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 address320
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 run324
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 terminal338
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" command358
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 seconds370
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 it423
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        else443
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 blink462
463  p.runShellCommand("hostname " + yunName); //change the current hostname464
465  p.runShellCommand("uci set system.@system[0].hostname='" + yunName + "'"); //change the hostname in uci466
467  p.runShellCommand("uci set arduino.@arduino[0].access_point_wifi_name='" + wifiAPname + "'");468
469  //this block resets the wifi psw470
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 passwors490
491  p.runShellCommand("uci commit"); //save the mods done via UCI492
493  p.runShellCommand("blink-stop"); //start the blue blink494
495  p.runShellCommand("wifi ");496}497
498long linuxBaud = 250000;499
500void startSerialTerminal() {501
502  SERIAL_PORT_USBVIRTUAL.begin(115200);  // open serial connection via USB-Serial503
504  SERIAL_PORT_HARDWARE.begin(linuxBaud); // open serial connection to Linux505}506
507bool commandMode = false;508void loopSerialTerminal() {509
510  // copy from USB-CDC to UART511
512  int c = SERIAL_PORT_USBVIRTUAL.read();    // read from USB-CDC513
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 mode521
522      } else {523
524        SERIAL_PORT_HARDWARE.write(c);      //    otherwise write char to UART525
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 57600533
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 115200539
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 250000545
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 500000551
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" command557
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 UART563
564        SERIAL_PORT_HARDWARE.write(c);      //        write char to UART565
566      }567
568      commandMode = false;                  //     in all cases exit from command mode569
570    }571
572  }573
574  // copy from UART to USB-CDC575
576  c = SERIAL_PORT_HARDWARE.read();          // read from UART577
578  if (c != -1) {                            // got anything?579
580    SERIAL_PORT_USBVIRTUAL.write(c);        //    write to USB-CDC581
582  }583}Last revision 2016/05/25 by SM
Suggested changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. You can read more on how to contribute in the contribution policy.
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.