├── README.md ├── Season 2 ├── Episode 1 - Hack your plant │ ├── hackyourplant │ │ ├── episode1_fritzing.png │ │ └── hackyourplant.ino │ └── readme.md ├── Episode 2 - Tinker with RGB │ ├── phototransistor │ │ ├── episode2_fritzing.png │ │ └── phototransistor.ino │ └── readme.md ├── Episode 3 - Retro game control │ ├── readme.md │ └── retroController │ │ ├── episode3_fritzing.png │ │ └── retroController.ino ├── Episode 4 - MKR1010 WiFi setup │ ├── MKR1010_config │ │ ├── MKR1010_config.ino │ │ └── episode4_fritzing.png │ └── readme.md ├── Episode 6 - LED matrix │ ├── PixelCrafter │ │ ├── PC2 │ │ │ ├── GClip.java │ │ │ ├── PC2.pde │ │ │ ├── UI.pde │ │ │ ├── colorpicker.pde │ │ │ ├── data │ │ │ │ ├── AdvoCut.ttf │ │ │ │ ├── head.gif │ │ │ │ └── miepsfonts.htm │ │ │ ├── mouse_and_keyboard.pde │ │ │ └── pixelmatrix.pde │ │ └── Readme.md │ ├── img │ │ └── pixelcrafter_window.png │ ├── readme.md │ └── realMatrix │ │ ├── episode6_fritzing.png │ │ ├── ledData.h │ │ └── realMatrix.ino ├── Episode 7 - Temperature & Humidity display │ ├── DHT_LCD │ │ ├── DHT_LCD.ino │ │ └── episode7_fritzing.png │ └── readme.md └── Episode 8 - Bluetooth Matrix Special │ ├── Matrix_BT │ ├── Matrix_BT.ino │ └── ledData.h │ ├── PC3 │ ├── GClip.java │ ├── PC3.pde │ ├── UI.pde │ ├── XXX_TO_DO.pde │ ├── colorpicker.pde │ ├── data │ │ ├── AdvoCut.ttf │ │ ├── head.gif │ │ └── miepsfonts.htm │ ├── mouse_and_keyboard.pde │ ├── palette.pde │ └── pixelmatrix.pde │ ├── img │ └── fritzing_episode8.png │ └── readme.md ├── Season 3 ├── Episode 1 - MKR1010 + TFT = Clock (Space Calendar I) │ ├── WiFi_RTC │ │ ├── WiFi_RTC.ino │ │ └── arduino_secrets.h │ ├── WiFi_RTC_revised │ │ ├── WiFi_RTC_revised.ino │ │ ├── arduino_secrets.h │ │ └── functions.ino │ ├── WiFi_RTC_screen │ │ ├── WiFi_RTC_screen.ino │ │ ├── arduino_secrets.h │ │ ├── functions.ino │ │ └── s03e01_fritzing.png │ ├── img │ │ └── s03e01_fritzing.png │ └── readme.md ├── Episode 3 - Anemometer with Arduino Uno │ ├── S03E03_Fritzing.png │ ├── readme.md │ └── windspeed │ │ └── windspeed.ino └── Episode 6 - Rain Sensor │ ├── fritzing_e4.png │ ├── rainsensor │ └── rainsensor.ino │ └── readme.md └── img └── livecast_1.png /README.md: -------------------------------------------------------------------------------- 1 | # Arduino Livecast 2 | 3 | The Arduino Livecast is an initiative inviting everyone to try making projects with digital electronics. D. Cuartielles with the help of Malmo University students: Josefine and Karl, runs a weekly YouTube segment where he talks, demoes, and discusses technology. 4 | 5 | [![Use NeoPixel screens by D. Cuartielles](img/livecast_1.png)](https://www.youtube.com/watch?v=CSY_eRZCTZk) 6 | 7 | *Click on the image to watch a video about using NeoPixel Matrixes, S02E06* 8 | 9 | The videos show projects made with Arduino UNO, MKR, NeoPixels, motors, buttons, LEDs ... and code. Feel free to download this repository, try it out, improve it, and send us comments. We will be glad to incorporate your ideas into future shows. 10 | 11 | Follow Arduino on [YouTube](https://www.youtube.com/subscription_center?add_user=arduinoteam), [Discord](https://discord.gg/KjW5CKp), and the [Arduino Forum](https://forum.arduino.cc). Join us and let's have fun learning together. 12 | 13 | ## Credits 14 | 15 | Thanks to: 16 | 17 | * The EU project *eCraft2Learn* that has kindly sponsored the birth of this livecast 18 | * Josefine & Karl from Malmo University 19 | * Our online contributors: [per1234](https://github.com/per1234) 20 | -------------------------------------------------------------------------------- /Season 2/Episode 1 - Hack your plant/hackyourplant/episode1_fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 1 - Hack your plant/hackyourplant/episode1_fritzing.png -------------------------------------------------------------------------------- /Season 2/Episode 1 - Hack your plant/hackyourplant/hackyourplant.ino: -------------------------------------------------------------------------------- 1 | /*Arduino Livecast Season 2, Episode 1 2 | Hack your plant*/ 3 | 4 | 5 | int potPin = A0; // select the input pin for the potentiometer 6 | int redLed = 2; // select the pin for the LED 7 | int yellowLed = 3; // select the pin for the LED 8 | int greenLed = 4; // select the pin for the LED 9 | 10 | int val = 0; // variable to store the value coming from the sensor 11 | 12 | void setup() { 13 | pinMode(redLed, OUTPUT); // declare the ledPin as an OUTPUT 14 | pinMode(yellowLed, OUTPUT); // declare the ledPin as an OUTPUT 15 | pinMode(greenLed, OUTPUT); // declare the ledPin as an OUTPUT 16 | Serial.begin(9600); 17 | } 18 | 19 | void loop() { 20 | val = analogRead(potPin); // read the value from the sensor 21 | Serial.println(val); // print the value to set thresholds 22 | 23 | //red 24 | if (val >= 900 && val <= 1023) { //set your own thresholds dependent on values 25 | digitalWrite(redLed, HIGH); // turn the ledPin on 26 | } 27 | else { 28 | digitalWrite(redLed, LOW); 29 | } 30 | 31 | //orange 32 | if (val >= 501 && val <= 899) { //set your own thresholds dependent on values 33 | digitalWrite(yellowLed, HIGH); // turn the ledPin on 34 | } 35 | else { 36 | digitalWrite(yellowLed, LOW); 37 | } 38 | 39 | //green 40 | if (val > 0 && val <= 500) { //set your own thresholds dependent on values 41 | digitalWrite(greenLed, HIGH); // turn the ledPin on 42 | } 43 | else { 44 | digitalWrite(greenLed, LOW); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Season 2/Episode 1 - Hack your plant/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 1 - Hack your plant 2 | 3 | 4 | This example will allow you collect data from your plant and give you notifications depending on the moist level of the plant. We are going to use a moist sensor and a couple of LEDs to indicate whether we have to water the plant or not. 5 | 6 | You can watch this project being done by David Cuartielles, the co-founder of Arduino on YouTube. 7 | 8 | [![Hack your plants with D. Cuartielles](https://img.youtube.com/vi/_VkSANzUnCw/0.jpg)](https://www.youtube.com/watch?v=_VkSANzUnCw) 9 | 10 | ## Ingredients 11 | 12 | - Arduino UNO (or any other Arduino boards) 13 | - Moist sensor 14 | - 1x red LED, 1x yellow LED, 1x green LED 15 | - 3x 220ohm resistors 16 | - Jumper wires 17 | 18 | 19 | ## Wiring 20 | ##### Connect the wires and components according to the fritzing below. 21 | ![Fritzing diagram](hackyourplant/episode1_fritzing.png "Fritzing diagram") 22 | 23 | 24 | 25 | ## Code 26 | 27 | ```sh 28 | int potPin = A0; // select the input pin for the potentiometer 29 | int redLed = 2; // select the pin for the LED 30 | int yellowLed = 3; // select the pin for the LED 31 | int greenLed = 4; // select the pin for the LED 32 | 33 | int val = 0; // variable to store the value coming from the sensor 34 | 35 | void setup() { 36 | pinMode(redLed, OUTPUT); // declare the ledPin as an OUTPUT 37 | pinMode(yellowLed, OUTPUT); // declare the ledPin as an OUTPUT 38 | pinMode(greenLed, OUTPUT); // declare the ledPin as an OUTPUT 39 | Serial.begin(9600); 40 | } 41 | 42 | void loop() { 43 | val = analogRead(potPin); // read the value from the sensor 44 | Serial.println(val); // print the value to set thresholds 45 | 46 | //red 47 | if (val >= 900 && val <= 1023) { //set your own thresholds dependent on values 48 | digitalWrite(redLed, HIGH); // turn the ledPin on 49 | } 50 | else { 51 | digitalWrite(redLed, LOW); 52 | } 53 | 54 | //orange 55 | if (val >= 501 && val <= 899) { //set your own thresholds dependent on values 56 | digitalWrite(yellowLed, HIGH); // turn the ledPin on 57 | } 58 | else { 59 | digitalWrite(yellowLed, LOW); 60 | } 61 | 62 | //green 63 | if (val > 0 && val <= 500) { //set your own thresholds dependent on values 64 | digitalWrite(greenLed, HIGH); // turn the ledPin on 65 | } 66 | else { 67 | digitalWrite(greenLed, LOW); 68 | } 69 | } 70 | ``` 71 | 72 | ## Start using 73 | 74 | After wiring and uploading the code, it is time to test it! 75 | - First we can try it out on a dry plant. It will generate a value that most likely is over 900, which will turn on the Red LED. 76 | - If we water the plant just a little bit and then try the moist sensor again, it will generate a different value, most likely between 500 & 900, and that will turn the Yellow LED on. 77 | - If we drown the plant in water, the moist sensor will give a very low value, which will turn on the Green LED. 78 | 79 | ## Outcome 80 | 81 | We have in this example created a functional moist-o-meter, which will notify you the state of your plant. High moist equals a low value, whereas low moist equals a high value. You can now find your own treshold and start hacking your plant! 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /Season 2/Episode 2 - Tinker with RGB/phototransistor/episode2_fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 2 - Tinker with RGB/phototransistor/episode2_fritzing.png -------------------------------------------------------------------------------- /Season 2/Episode 2 - Tinker with RGB/phototransistor/phototransistor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Control a RGB LED with a phototransistor 3 | 4 | Map the values of a phototransistors to control 5 | an RGB LED, using multiple if statements 6 | 7 | (c) Karl, Josefine and Davide for Arduino, 2018 8 | */ 9 | 10 | 11 | int photoPin = A0; 12 | int photoValue = 0; 13 | const int redPin = 5; 14 | const int greenPin = 6; 15 | const int bluePin = 9; 16 | 17 | void setup() { 18 | 19 | Serial.begin(9600); 20 | 21 | pinMode(redPin, OUTPUT); 22 | pinMode(greenPin, OUTPUT); 23 | pinMode(bluePin, OUTPUT); 24 | } 25 | 26 | void loop() { 27 | //stores the value of A0 in a variable 28 | photoValue = analogRead(photoPin); 29 | Serial.println(photoValue); 30 | 31 | //the following code will change the RGBs color depending on the value of the photoresistor 32 | 33 | //if we cover the photoresistor, the RGB will give a strange color 34 | if (photoValue >= 1 && photoValue <= 5) { 35 | analogWrite(redPin, 255); 36 | analogWrite(greenPin, 127); 37 | analogWrite(bluePin, 80); 38 | } 39 | //if our hand gets close enough, the RGB will turn blue 40 | if (photoValue >= 6 && photoValue <= 12) { 41 | analogWrite(redPin, 0); 42 | analogWrite(greenPin, 0); 43 | analogWrite(bluePin, 255); 44 | } 45 | //if our hand is semi-far away, the RGB will turn green 46 | if (photoValue >= 13 && photoValue <= 20) { 47 | analogWrite(redPin, 0); 48 | analogWrite(greenPin, 255); 49 | analogWrite(bluePin, 0); 50 | } 51 | 52 | //if we do nothing, the RGB will stay red 53 | if (photoValue >= 21 && photoValue <= 50) { 54 | analogWrite(redPin, 255); 55 | analogWrite(greenPin, 0); 56 | analogWrite(bluePin, 0); 57 | } 58 | //if we use a flashlight on the photoresistor, the RGB will turn purple 59 | if (photoValue >= 50) { 60 | analogWrite(redPin, 255); 61 | analogWrite(greenPin, 0); 62 | analogWrite(bluePin, 255); 63 | } 64 | //we use a delay so the serial port doesn't get too busy 65 | delay(100); 66 | } 67 | -------------------------------------------------------------------------------- /Season 2/Episode 2 - Tinker with RGB/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 2 - Tinker with RGB 2 | This example will allow you to control an RGB LED with the help of a phototransistor. The phototransistor alters the current depending on how much light it receives, and gives out a value. With this we can map out what kind of colour the RGB led will have. 3 | 4 | 5 | ## Ingredients 6 | - Arduino UNO 7 | - 1x RGB LED 8 | - 1x phototransistor 9 | - 1x 220 ohm resistor 10 | - Jumper wires 11 | 12 | 13 | ## Wiring 14 | *Connect the wires and components according to the fritzing below.* 15 | ![Fritzing diagram](phototransistor/episode2_fritzing.png "Fritzing diagram") 16 | 17 | 18 | 19 | ## Code 20 | 21 | ```sh 22 | 23 | int photoPin = A0; 24 | int photoValue = 0; 25 | const int redPin = 5; 26 | const int greenPin = 6; 27 | const int bluePin = 9; 28 | 29 | void setup() { 30 | 31 | Serial.begin(9600); 32 | 33 | pinMode(redPin, OUTPUT); 34 | pinMode(greenPin, OUTPUT); 35 | pinMode(bluePin, OUTPUT); 36 | } 37 | 38 | void loop() { 39 | //stores the value of A0 in a variable 40 | photoValue = analogRead(photoPin); 41 | Serial.println(photoValue); 42 | 43 | //the following code will change the RGBs color depending on the value of the photoresistor 44 | 45 | //if we cover the photoresistor, the RGB will give a strange color 46 | if (photoValue >= 1 && photoValue <= 5) { 47 | analogWrite(redPin, (255, 255, 255)); 48 | analogWrite(greenPin, (127, 127, 127)); 49 | analogWrite(bluePin, (80 , 80, 80)); 50 | } 51 | //if our hand gets close enough, the RGB will turn blue 52 | if (photoValue >= 6 && photoValue <= 12) { 53 | analogWrite(redPin, (0, 0, 0)); 54 | analogWrite(greenPin, (0, 0, 0)); 55 | analogWrite(bluePin, (255, 255, 255)); 56 | } 57 | //if our hand is semi-far away, the RGB will turn green 58 | if (photoValue >= 13 && photoValue <= 20) { 59 | analogWrite(redPin, (0, 0, 0)); 60 | analogWrite(greenPin, (255, 255, 255)); 61 | analogWrite(bluePin, (0, 0, 0)); 62 | } 63 | 64 | //if we do nothing, the RGB will stay red 65 | if (photoValue >= 21 && photoValue <= 50) { 66 | analogWrite(redPin, (255, 255, 255)); 67 | analogWrite(greenPin, (0, 0, 0)); 68 | analogWrite(bluePin, (0, 0, 0)); 69 | } 70 | //if we use a flashlight on the photoresistor, the RGB will turn purple 71 | if (photoValue >= 50) { 72 | analogWrite(redPin, (255, 255, 255)); 73 | analogWrite(greenPin, (0, 0, 0)); 74 | analogWrite(bluePin, (255, 255, 255)); 75 | } 76 | //we use a delay so the serial port doesn't get too busy 77 | delay(100); 78 | } 79 | 80 | ``` 81 | 82 | ## Start using 83 | 84 | After wiring and uploading the code, we can now start using this example. The thresholds set in the code, for e.g. **(photovalue >= 50)**, will trigger a function if the value is over 50. You can now make your own tresholds for the RGB to change accordingly. 85 | 86 | 87 | ## Outcome 88 | 89 | This is a classic example of how an input and output works. What we have learned here is to grab a value from a specific sensor, create **if statements** to check if the value is within a certain parameter, and execute a function afterwards. We have also learned how RGB LEDs work and how we change its colour. 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /Season 2/Episode 3 - Retro game control/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 3 - Retro Game Control 2 | This example will allow you to play your favourite retro game with an Arduino-built controller by using keypresses. This example has 5 buttons that each simulates a keypress that we have created. 3 | 4 | 5 | 6 | ## Ingredients 7 | - Arduino Micro 8 | - 5 buttons 9 | - 5 resistors 10 | - Jumper wires (female to male recommended for mapping out your controls) 11 | 12 | 13 | ## Wiring 14 | #### Connect the wires and components according to the fritzing below. 15 | ![Fritzing diagram](retroController/episode3_fritzing.png "Fritzing diagram") 16 | 17 | 18 | 19 | ## Code 20 | 21 | ```sh 22 | #include "Keyboard.h" 23 | 24 | //declaring button pins 25 | const int buttonPin = 2; 26 | const int buttonPin1 = 3; 27 | const int buttonPin2 = 4; 28 | const int buttonPin3 = 5; 29 | const int buttonPin4 = 6; 30 | 31 | 32 | int previousButtonState = HIGH; 33 | int previousButtonState1 = HIGH; 34 | int previousButtonState2 = HIGH; 35 | int previousButtonState3 = HIGH; 36 | int previousButtonState4 = HIGH; 37 | 38 | 39 | 40 | void setup() { 41 | //declare the buttons as input_pullup 42 | pinMode(buttonPin, INPUT_PULLUP); 43 | pinMode(buttonPin1, INPUT_PULLUP); 44 | pinMode(buttonPin2, INPUT_PULLUP); 45 | pinMode(buttonPin3, INPUT_PULLUP); 46 | pinMode(buttonPin4, INPUT_PULLUP); 47 | 48 | Keyboard.begin(); 49 | } 50 | 51 | void loop() { 52 | //checking the state of the button 53 | int buttonState = digitalRead(buttonPin); 54 | int buttonState1 = digitalRead(buttonPin1); 55 | int buttonState2 = digitalRead(buttonPin2); 56 | int buttonState3 = digitalRead(buttonPin3); 57 | int buttonState4 = digitalRead(buttonPin4); 58 | 59 | //replaces button press with UP arrow 60 | if (buttonState == LOW && previousButtonState == HIGH) { 61 | // and it's currently pressed: 62 | Keyboard.press(218); 63 | } 64 | 65 | if (buttonState == HIGH && previousButtonState == LOW) { 66 | // and it's currently released: 67 | Keyboard.release(218); 68 | } 69 | 70 | //replaces button press with DOWN arrow 71 | if (buttonState1 == LOW && previousButtonState1 == HIGH) { 72 | // and it's currently pressed: 73 | Keyboard.press(217); 74 | } 75 | 76 | if (buttonState1 == HIGH && previousButtonState1 == LOW) { 77 | // and it's currently released: 78 | Keyboard.release(217); 79 | } 80 | 81 | //replaces button press with RIGHT arrow 82 | if (buttonState2 == LOW && previousButtonState2 == HIGH) { 83 | // and it's currently pressed: 84 | Keyboard.press(215); 85 | } 86 | 87 | if (buttonState2 == HIGH && previousButtonState2 == LOW) { 88 | // and it's currently released: 89 | Keyboard.release(215); 90 | } 91 | 92 | //replaces button press with LEFT arrow 93 | if (buttonState3 == LOW && previousButtonState3 == HIGH) { 94 | // and it's currently pressed: 95 | Keyboard.press(216); 96 | } 97 | 98 | if (buttonState3 == HIGH && previousButtonState3 == LOW) { 99 | // and it's currently released: 100 | Keyboard.release(216); 101 | } 102 | 103 | //replaces button press with SPACE BAR 104 | if (buttonState4 == LOW && previousButtonState4 == HIGH) { 105 | // and it's currently pressed: 106 | Keyboard.press(32); 107 | } 108 | 109 | if (buttonState4 == HIGH && previousButtonState4 == LOW) { 110 | // and it's currently released: 111 | Keyboard.release(32); 112 | } 113 | 114 | //checking the previous state of the button 115 | 116 | previousButtonState = buttonState; 117 | previousButtonState1 = buttonState1; 118 | previousButtonState2 = buttonState2; 119 | previousButtonState3 = buttonState3; 120 | previousButtonState4 = buttonState4; 121 | 122 | } 123 | 124 | ``` 125 | 126 | ## Start using 127 | 128 | After wiring and uploading the code, we can now start using the controller. What happens in the code is that if a button is pressed, it will simulate a specific keypress. For example, Keyboard.press(218); will be the same as using the UP arrow on your regular keyboard. For a complete reference list of what keycodes you want to use, check out: 129 | - 130 | - 131 | 132 | 133 | ## Outcome 134 | 135 | With this knowledge you can start exploring different ways of interacting with your computer, it doesn't have to be confined to games. You can for example find the keycode for your volume buttons on your computer, or make a very large space bar for aggressive writing sessions. 136 | 137 | After completing this example, we can also encourage you to create your own set of buttons, by using copper tape and simple materials you can find at home. 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /Season 2/Episode 3 - Retro game control/retroController/episode3_fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 3 - Retro game control/retroController/episode3_fritzing.png -------------------------------------------------------------------------------- /Season 2/Episode 3 - Retro game control/retroController/retroController.ino: -------------------------------------------------------------------------------- 1 | #include "Keyboard.h" 2 | 3 | //declaring button pins 4 | const int buttonPin = 2; 5 | const int buttonPin1 = 3; 6 | const int buttonPin2 = 4; 7 | const int buttonPin3 = 5; 8 | const int buttonPin4 = 6; 9 | 10 | 11 | int previousButtonState = HIGH; 12 | int previousButtonState1 = HIGH; 13 | int previousButtonState2 = HIGH; 14 | int previousButtonState3 = HIGH; 15 | int previousButtonState4 = HIGH; 16 | 17 | 18 | 19 | void setup() { 20 | //declare the buttons as input_pullup 21 | pinMode(buttonPin, INPUT_PULLUP); 22 | pinMode(buttonPin1, INPUT_PULLUP); 23 | pinMode(buttonPin2, INPUT_PULLUP); 24 | pinMode(buttonPin3, INPUT_PULLUP); 25 | pinMode(buttonPin4, INPUT_PULLUP); 26 | 27 | 28 | Keyboard.begin(); 29 | } 30 | 31 | void loop() { 32 | //checking the state of the button 33 | int buttonState = digitalRead(buttonPin); 34 | int buttonState1 = digitalRead(buttonPin1); 35 | int buttonState2 = digitalRead(buttonPin2); 36 | int buttonState3 = digitalRead(buttonPin3); 37 | int buttonState4 = digitalRead(buttonPin4); 38 | 39 | 40 | //replaces button press with UP arrow 41 | if (buttonState == LOW && previousButtonState == HIGH) { 42 | // and it's currently pressed: 43 | Keyboard.press(218); 44 | } 45 | 46 | if (buttonState == HIGH && previousButtonState == LOW) { 47 | // and it's currently released: 48 | Keyboard.release(218); 49 | } 50 | 51 | //replaces button press with DOWN arrow 52 | if (buttonState1 == LOW && previousButtonState1 == HIGH) { 53 | // and it's currently pressed: 54 | Keyboard.press(217); 55 | } 56 | 57 | if (buttonState1 == HIGH && previousButtonState1 == LOW) { 58 | // and it's currently released: 59 | Keyboard.release(217); 60 | } 61 | 62 | //replaces button press with RIGHT arrow 63 | if (buttonState2 == LOW && previousButtonState2 == HIGH) { 64 | // and it's currently pressed: 65 | Keyboard.press(215); 66 | } 67 | 68 | if (buttonState2 == HIGH && previousButtonState2 == LOW) { 69 | // and it's currently released: 70 | Keyboard.release(215); 71 | } 72 | 73 | //replaces button press with LEFT arrow 74 | if (buttonState3 == LOW && previousButtonState3 == HIGH) { 75 | // and it's currently pressed: 76 | Keyboard.press(216); 77 | } 78 | 79 | if (buttonState3 == HIGH && previousButtonState3 == LOW) { 80 | // and it's currently released: 81 | Keyboard.release(216); 82 | } 83 | 84 | //replaces button press with SPACE BAR 85 | if (buttonState4 == LOW && previousButtonState4 == HIGH) { 86 | // and it's currently pressed: 87 | Keyboard.press(32); 88 | } 89 | 90 | if (buttonState4 == HIGH && previousButtonState4 == LOW) { 91 | // and it's currently released: 92 | Keyboard.release(32); 93 | } 94 | 95 | //checking the previous state of the button 96 | 97 | previousButtonState = buttonState; 98 | previousButtonState1 = buttonState1; 99 | previousButtonState2 = buttonState2; 100 | previousButtonState3 = buttonState3; 101 | previousButtonState4 = buttonState4; 102 | 103 | 104 | 105 | } 106 | 107 | -------------------------------------------------------------------------------- /Season 2/Episode 4 - MKR1010 WiFi setup/MKR1010_config/MKR1010_config.ino: -------------------------------------------------------------------------------- 1 | /* 2 | MKR1010 WiFi setup. 3 | 4 | Control LEDs and a servo with your phone/computer 5 | over local WiFi. 6 | 7 | (c) 2018 Karl, Josefine and David for Arduino. 8 | 9 | based on code by (c) m.ehrndal, Arduino LLC.2013-2016 10 | */ 11 | 12 | //libraries 13 | #include 14 | #include 15 | #include 16 | 17 | char ssid[] = ""; // your network SSID (name) between the " " 18 | char pass[] = ""; // your network password between the " " 19 | int keyIndex = 0; // your network key Index number (needed only for WEP) 20 | 21 | int status = WL_IDLE_STATUS; //connection status 22 | WiFiServer server(80); //server socket 23 | 24 | //special characters 25 | char quote = '"'; 26 | char slash = '/'; 27 | 28 | Servo myservo; 29 | 30 | void setup() { 31 | Serial.begin(9600); // initialize serial communication 32 | pinMode(6, OUTPUT); // set the LED pin mode 33 | pinMode(7, OUTPUT); 34 | myservo.attach(9); 35 | myservo.write(45); 36 | 37 | // check for the presence of the shield: 38 | if (WiFi.status() == WL_NO_SHIELD) { 39 | Serial.println("WiFi shield not present"); 40 | while (true); // don't continue 41 | } 42 | 43 | // attempt to connect to WiFi network: 44 | while ( status != WL_CONNECTED) { 45 | Serial.print("Attempting to connect to Network named: "); 46 | Serial.println(ssid); // print the network name (SSID); 47 | 48 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 49 | status = WiFi.begin(ssid, pass); 50 | // wait 10 seconds for connection: 51 | delay(10000); 52 | } 53 | server.begin(); // start the web server on port 80 54 | printWiFiStatus(); // you're connected now, so print out the status 55 | } 56 | 57 | 58 | void loop() { 59 | 60 | // attempt to connect to WiFi network: 61 | while ( status != WL_CONNECTED) { 62 | Serial.print("Attempting to connect to Network named: "); 63 | Serial.println(ssid); // print the network name (SSID); 64 | 65 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 66 | status = WiFi.begin(ssid, pass); 67 | // wait 10 seconds for connection: 68 | delay(10000); 69 | } 70 | 71 | WiFiClient client = server.available(); // listen for incoming clients 72 | 73 | if (client) { // if you get a client, 74 | Serial.println("new client"); // print a message out the serial port 75 | String currentLine = ""; // make a String to hold incoming data from the client 76 | while (client.connected()) { // loop while the client's connected 77 | if (client.available()) { // if there's bytes to read from the client, 78 | char c = client.read(); // read a byte, then 79 | Serial.write(c); // print it out the serial monitor 80 | if (c == '\n') { // if the byte is a newline character 81 | 82 | // if the current line is blank, you got two newline characters in a row. 83 | // that's the end of the client HTTP request, so send a response: 84 | if (currentLine.length() == 0) { 85 | // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) 86 | // and a content-type so the client knows what's coming, then a blank line: 87 | client.println("HTTP/1.1 200 OK"); 88 | client.println("Content-type:text/html"); 89 | client.println(); 90 | // the content of the HTTP response follows the header: 91 | client.println(""); 92 | client.print(""); 93 | client.print(""); 103 | client.print(""); 104 | client.print(""); 105 | client.println("


CONTROL YOUR ARDUINO

"); 106 | client.println("
"); 107 | client.println("

"); 108 | client.println(""); 109 | client.println(""); 110 | client.println(""); 111 | client.println(""); 112 | client.println(""); 113 | 114 | // The HTTP response ends with another blank line: 115 | client.println(); 116 | // break out of the while loop: 117 | break; 118 | } 119 | else { // if you got a newline, then clear currentLine: 120 | currentLine = ""; 121 | } 122 | } 123 | else if (c != '\r') { // if you got anything else but a carriage return character, 124 | currentLine += c; // add it to the end of the currentLine 125 | } 126 | 127 | // Check to see if the client request was "GET /H" or "GET /L" or "GET /X": 128 | if (currentLine.endsWith("GET /H")) { 129 | digitalWrite(7, HIGH); // GET /H turns the pin 6 LED on 130 | } 131 | if (currentLine.endsWith("GET /L")) { 132 | digitalWrite(7, LOW); // GET /L turns the pin 6 LED off 133 | } 134 | if (currentLine.endsWith("GET /P")) { 135 | myservo.write(40); // GET /P turns the servo to 45 136 | } 137 | if (currentLine.endsWith("GET /Y")) { 138 | myservo.write(30); // GET /Y turns servo to 90 139 | } 140 | if (currentLine.endsWith("GET /X")) { 141 | digitalWrite(6, HIGH); // GET /L turns the pin 6 LED off 142 | delay(500); 143 | digitalWrite(6, LOW); 144 | delay(500); 145 | digitalWrite(6, HIGH); 146 | delay(500); 147 | digitalWrite(6, LOW); 148 | delay(500); 149 | digitalWrite(6, HIGH); 150 | delay(500); 151 | digitalWrite(6, LOW); 152 | } 153 | 154 | 155 | } 156 | } 157 | // close the connection: 158 | client.stop(); 159 | Serial.println("client disonnected"); 160 | } 161 | } 162 | 163 | void printWiFiStatus() { 164 | // print the SSID of the network you're attached to: 165 | Serial.print("SSID: "); 166 | Serial.println(WiFi.SSID()); 167 | 168 | // print your WiFi shield's IP address: 169 | IPAddress ip = WiFi.localIP(); 170 | Serial.print("IP Address: "); 171 | Serial.println(ip); 172 | 173 | // print the received signal strength: 174 | long rssi = WiFi.RSSI(); 175 | Serial.print("signal strength (RSSI):"); 176 | Serial.print(rssi); 177 | Serial.println(" dBm"); 178 | // print where to go in a browser: 179 | Serial.print("To see this page in action, open a browser to http://"); 180 | Serial.println(ip); 181 | } 182 | 183 | -------------------------------------------------------------------------------- /Season 2/Episode 4 - MKR1010 WiFi setup/MKR1010_config/episode4_fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 4 - MKR1010 WiFi setup/MKR1010_config/episode4_fritzing.png -------------------------------------------------------------------------------- /Season 2/Episode 4 - MKR1010 WiFi setup/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 4 - MKR1010 WiFi setup 2 | In this example we will host a webserver on the Arduino board which we can interact with over the phone or computer. With the help of this, we can turn an LED on/off, make an LED blink and turn a servo left and right from an interface that you can access on your phone or computer. 3 | 4 | You can watch this project being done by David Cuartielles, the co-founder of Arduino, by clicking into this link: https://www.youtube.com/watch?v=H0p7GVPdlyU&t=1150s 5 | 6 | 7 | 8 | ## Ingredients 9 | - Arduino MKR1010 board 10 | - 2x LEDs 11 | - 1x servo 12 | - Jumper wires 13 | 14 | 15 | ## Wiring 16 | ##### Connect the wires and components according to the fritzing below. 17 | ![Fritzing diagram](MKR1010_config/episode4_fritzing.png "Fritzing diagram") 18 | 19 | 20 | 21 | ## Code 22 | 23 | ```sh 24 | 25 | /* 26 | MKR1010 WiFi setup. 27 | 28 | Control LEDs and a servo with your phone/computer 29 | over local WiFi. 30 | 31 | (c) 2018 Karl, Josefine and David for Arduino. 32 | 33 | based on code by (c) m.ehrndal, Arduino LLC.2013-2016 34 | */ 35 | 36 | //libraries 37 | #include 38 | #include 39 | #include 40 | 41 | char ssid[] = ""; // your network SSID (name) between the " " 42 | char pass[] = ""; // your network password between the " " 43 | int keyIndex = 0; // your network key Index number (needed only for WEP) 44 | 45 | int status = WL_IDLE_STATUS; //connection status 46 | WiFiServer server(80); //server socket 47 | 48 | //special characters 49 | char quote = '"'; 50 | char slash = '/'; 51 | 52 | Servo myservo; 53 | 54 | void setup() { 55 | Serial.begin(9600); // initialize serial communication 56 | pinMode(6, OUTPUT); // set the LED pin mode 57 | pinMode(7, OUTPUT); 58 | myservo.attach(9); 59 | myservo.write(45); 60 | 61 | // check for the presence of the shield: 62 | if (WiFi.status() == WL_NO_SHIELD) { 63 | Serial.println("WiFi shield not present"); 64 | while (true); // don't continue 65 | } 66 | 67 | // attempt to connect to WiFi network: 68 | while ( status != WL_CONNECTED) { 69 | Serial.print("Attempting to connect to Network named: "); 70 | Serial.println(ssid); // print the network name (SSID); 71 | 72 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 73 | status = WiFi.begin(ssid, pass); 74 | // wait 10 seconds for connection: 75 | delay(10000); 76 | } 77 | server.begin(); // start the web server on port 80 78 | printWiFiStatus(); // you're connected now, so print out the status 79 | } 80 | 81 | 82 | void loop() { 83 | 84 | // attempt to connect to WiFi network: 85 | while ( status != WL_CONNECTED) { 86 | Serial.print("Attempting to connect to Network named: "); 87 | Serial.println(ssid); // print the network name (SSID); 88 | 89 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 90 | status = WiFi.begin(ssid, pass); 91 | // wait 10 seconds for connection: 92 | delay(10000); 93 | } 94 | 95 | WiFiClient client = server.available(); // listen for incoming clients 96 | 97 | if (client) { // if you get a client, 98 | Serial.println("new client"); // print a message out the serial port 99 | String currentLine = ""; // make a String to hold incoming data from the client 100 | while (client.connected()) { // loop while the client's connected 101 | if (client.available()) { // if there's bytes to read from the client, 102 | char c = client.read(); // read a byte, then 103 | Serial.write(c); // print it out the serial monitor 104 | if (c == '\n') { // if the byte is a newline character 105 | 106 | // if the current line is blank, you got two newline characters in a row. 107 | // that's the end of the client HTTP request, so send a response: 108 | if (currentLine.length() == 0) { 109 | // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) 110 | // and a content-type so the client knows what's coming, then a blank line: 111 | client.println("HTTP/1.1 200 OK"); 112 | client.println("Content-type:text/html"); 113 | client.println(); 114 | // the content of the HTTP response follows the header: 115 | client.println(""); 116 | client.print(""); 117 | client.print(""); 127 | client.print(""); 128 | client.print(""); 129 | client.println("


CONTROL YOUR ARDUINO

"); 130 | client.println("
"); 131 | client.println("

"); 132 | client.println(""); 133 | client.println(""); 134 | client.println(""); 135 | client.println(""); 136 | client.println(""); 137 | 138 | // The HTTP response ends with another blank line: 139 | client.println(); 140 | // break out of the while loop: 141 | break; 142 | } 143 | else { // if you got a newline, then clear currentLine: 144 | currentLine = ""; 145 | } 146 | } 147 | else if (c != '\r') { // if you got anything else but a carriage return character, 148 | currentLine += c; // add it to the end of the currentLine 149 | } 150 | 151 | // Check to see if the client request was "GET /H" or "GET /L" or "GET /X": 152 | if (currentLine.endsWith("GET /H")) { 153 | digitalWrite(7, HIGH); // GET /H turns the pin 6 LED on 154 | } 155 | if (currentLine.endsWith("GET /L")) { 156 | digitalWrite(7, LOW); // GET /L turns the pin 6 LED off 157 | } 158 | if (currentLine.endsWith("GET /P")) { 159 | myservo.write(40); // GET /P turns the servo to 45 160 | } 161 | if (currentLine.endsWith("GET /Y")) { 162 | myservo.write(30); // GET /Y turns servo to 90 163 | } 164 | if (currentLine.endsWith("GET /X")) { 165 | digitalWrite(6, HIGH); // GET /L turns the pin 6 LED off 166 | delay(500); 167 | digitalWrite(6, LOW); 168 | delay(500); 169 | digitalWrite(6, HIGH); 170 | delay(500); 171 | digitalWrite(6, LOW); 172 | delay(500); 173 | digitalWrite(6, HIGH); 174 | delay(500); 175 | digitalWrite(6, LOW); 176 | } 177 | 178 | 179 | } 180 | } 181 | // close the connection: 182 | client.stop(); 183 | Serial.println("client disonnected"); 184 | } 185 | } 186 | 187 | void printWiFiStatus() { 188 | // print the SSID of the network you're attached to: 189 | Serial.print("SSID: "); 190 | Serial.println(WiFi.SSID()); 191 | 192 | // print your WiFi shield's IP address: 193 | IPAddress ip = WiFi.localIP(); 194 | Serial.print("IP Address: "); 195 | Serial.println(ip); 196 | 197 | // print the received signal strength: 198 | long rssi = WiFi.RSSI(); 199 | Serial.print("signal strength (RSSI):"); 200 | Serial.print(rssi); 201 | Serial.println(" dBm"); 202 | // print where to go in a browser: 203 | Serial.print("To see this page in action, open a browser to http://"); 204 | Serial.println(ip); 205 | } 206 | 207 | 208 | 209 | ``` 210 | 211 | ## Start using 212 | 213 | After wiring and uploading the code, we can now access the MKR1010. The board attempts to connect to the WiFi, which you can follow in the Serial Monitor. Once it is connected, it will provide an ip address. Copy this link and access it through your computer and phone. You will then get an interface with a few buttons that you can interact with. The stylesheet is not hosted on Arduino, it is grabbed from an external source. 214 | 215 | 216 | ## Outcome 217 | 218 | We have in this example managed to control an Arduino MKR1010 over the local WiFi, and from here we can try out different components that we can control remotely. The MKR1010 no longer has to be connected to the computer and can be accessed from anywhere, as long as it has power and is within reach of the local WiFi. 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/GClip.java: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the GUI for Processing library 3 | http://www.lagers.org.uk/g4p/index.html 4 | http://gui4processing.googlecode.com/svn/trunk/ 5 | 6 | Copyright (c) 2008-09 Peter Lager 7 | 8 | To use the clipboard in your code: 9 | // Copy to clipboard 10 | GClip.copy(n1); 11 | // Get clipboard contents into another string 12 | n2 = GClip.paste(); 13 | 14 | The actual code to create the clipbaord, copy and paste were 15 | taken taken from a similar GUI library Interfascia ALPHA 002 -- 16 | http://superstable.net/interfascia/ produced by Brenden Berg 17 | The main change is to provide static copy and paste methods to 18 | separate the clipboard logic from the component logic and provide 19 | global access. 20 | 21 | This library is free software; you can redistribute it and/or 22 | modify it under the terms of the GNU Lesser General Public 23 | License as published by the Free Software Foundation; either 24 | version 2.1 of the License, or (at your option) any later version. 25 | 26 | This library is distributed in the hope that it will be useful, 27 | but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29 | Lesser General Public License for more details. 30 | 31 | You should have received a copy of the GNU Lesser General 32 | Public License along with this library; if not, write to the 33 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 34 | Boston, MA 02111-1307 USA 35 | */ 36 | 37 | import java.awt.Toolkit; 38 | import java.awt.datatransfer.Clipboard; 39 | import java.awt.datatransfer.ClipboardOwner; 40 | import java.awt.datatransfer.DataFlavor; 41 | import java.awt.datatransfer.StringSelection; 42 | import java.awt.datatransfer.Transferable; 43 | 44 | /* 45 | * I wanted to implement copying and pasting to the clipboard using static 46 | * methods to simplify the sharing of a single clipboard over all classes. 47 | * The need to implement the ClipboardOwner interface requires an object so 48 | * this class creates an object the first time an attempt to copy or paste 49 | * is used. 50 | * 51 | * All methods are private except copy() and paste() - lostOwnership() 52 | * has to be public because of the Clipboard owner interface. 53 | * 54 | * @author Peter Lager 55 | * 56 | */ 57 | 58 | /** 59 | * This provides clipboard functionality for text and is currently only used by the 60 | * GTextField class. 61 | * 62 | * @author Peter Lager 63 | */ 64 | public class GClip implements ClipboardOwner { 65 | /** 66 | * Static reference to enforce singleton pattern 67 | */ 68 | private static GClip gclip = null; 69 | 70 | /** 71 | * Class attribute to reference the programs clipboard 72 | */ 73 | private Clipboard clipboard = null; 74 | 75 | /** 76 | * Copy a string to the clipboard 77 | * @param chars 78 | */ 79 | public static boolean copy(String chars) { 80 | if (gclip == null) 81 | gclip = new GClip(); 82 | return gclip.copyString(chars); 83 | } 84 | 85 | /** 86 | * Get a string from the clipboard 87 | * @return the string on the clipboard 88 | */ 89 | public static String paste() { 90 | if (gclip == null) 91 | gclip = new GClip(); 92 | return gclip.pasteString(); 93 | } 94 | 95 | /** 96 | * Ctor is private so clipboard is only created when a copy or paste is 97 | * attempted and one does not exist already. 98 | */ 99 | private GClip() { 100 | if (clipboard == null) { 101 | makeClipboardObject(); 102 | } 103 | } 104 | 105 | /** 106 | * If security permits use the system clipboard otherwise create 107 | * our own application clipboard. 108 | */ 109 | private void makeClipboardObject() { 110 | SecurityManager security = System.getSecurityManager(); 111 | if (security != null) { 112 | try { 113 | security.checkSystemClipboardAccess(); 114 | clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 115 | } 116 | catch (SecurityException e) { 117 | clipboard = new Clipboard("Application Clipboard"); 118 | } 119 | } 120 | else { 121 | try { 122 | clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 123 | } 124 | catch (Exception e) { 125 | // THIS IS DUMB - true but is there another way - I think not 126 | } 127 | } 128 | } 129 | 130 | /** 131 | * Copy a string to the clipboard. If the Clipboard has not been created 132 | * then create it. 133 | * @return true for a successful copy to clipboard 134 | */ 135 | private boolean copyString(String chars) { 136 | if (clipboard == null) 137 | makeClipboardObject(); 138 | if (clipboard != null) { 139 | StringSelection fieldContent = new StringSelection (chars); 140 | clipboard.setContents (fieldContent, this); 141 | return true; 142 | } 143 | return false; 144 | } 145 | 146 | /** 147 | * Gets a string from the clipboard. If there is no Clipboard 148 | * then create it. 149 | * @return 150 | */ 151 | private String pasteString() { 152 | // If there is no clipboard then there is nothing to paste 153 | if (clipboard == null) { 154 | makeClipboardObject(); 155 | return ""; 156 | } 157 | // We have a clipboard so get the string if we can 158 | Transferable clipboardContent = clipboard.getContents(this); 159 | if ((clipboardContent != null) && 160 | (clipboardContent.isDataFlavorSupported(DataFlavor.stringFlavor))) { 161 | try { 162 | String tempString; 163 | tempString = (String) clipboardContent.getTransferData(DataFlavor.stringFlavor); 164 | return tempString; 165 | } 166 | catch (Exception e) { 167 | e.printStackTrace (); 168 | } 169 | } 170 | return ""; 171 | } 172 | 173 | /** 174 | * Reqd by ClipboardOwner interface 175 | */ 176 | public void lostOwnership(Clipboard clipboard, Transferable contents) { 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/PC2.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Pixel Crafter v0002 3 | 4 | (c) 2018 David Cuartielless for Arduino 5 | 6 | Uses ControlP5 for UI elements (but NOT color picker) 7 | Uses color picker code as found on the Processing forum: https://forum.processing.org/one/topic/processing-color-picker.html 8 | Uses AdvoCut font from Marc Andre Misman, (c) 2001 9 | Clipboard code from: https://forum.processing.org/one/topic/copy-and-paste.html#25080000001711515.html 10 | */ 11 | 12 | import controlP5.*; 13 | import processing.serial.*; 14 | 15 | boolean serialOn = false; 16 | 17 | // UI elements that need to be declared here 18 | UI ui; 19 | ControlP5 cp5; 20 | PFont font; 21 | 22 | String ver = "v0002 alpha"; 23 | 24 | Serial myPort; 25 | 26 | void setup() { 27 | size( 800, 730 ); 28 | 29 | cp5 = new ControlP5(this); 30 | ui = new UI(30, 30); 31 | 32 | // font related code 33 | // Uncomment the following two lines to see the available fonts 34 | //String[] fontList = PFont.list(); 35 | //printArray(fontList); 36 | font = createFont("AdvoCut", 50); 37 | textFont(font); 38 | 39 | // include serial port 40 | if (serialOn) myPort = new Serial(this, "/dev/ttyACM0", 9600); 41 | } 42 | 43 | void draw() { 44 | background(200); 45 | ui.update(); 46 | } 47 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/UI.pde: -------------------------------------------------------------------------------- 1 | public class UI { 2 | // vars 3 | int x = 0, y = 0; // UI coordinates 4 | int w = 20, h = 20; // size of the pixel matrix in our self-made pixels 5 | int s = 20, ms = 2; // size of each pixel in dots 6 | PIXEL_MATRIX mpix; 7 | PIXEL_MATRIX pix; 8 | ColorPicker cp; 9 | Textarea codeTextarea; 10 | CheckBox checkbox; 11 | Button buttonCopyText; 12 | String code = ""; 13 | int outputMode = 0; // by default do not invert every other output array (0) 14 | // invert output with (1) 15 | 16 | // constructor 17 | UI () { 18 | mpix = new PIXEL_MATRIX(x + 40, y + 10, ms); 19 | pix = new PIXEL_MATRIX(x + 40, y + 40, s); 20 | cp = new ColorPicker( x + 40 + w * s + 10, y + 40, 200, 200, 255 ); 21 | // UI elements related class 22 | codeTextarea = cp5.addTextarea("txt") 23 | .setPosition(x+40, y + h*s + 50) 24 | .setSize(400, 200) 25 | .setFont(createFont("courier", 12)) 26 | .setLineHeight(14) 27 | .setColor(color(128)) 28 | .setColorBackground(color(255, 100)) 29 | .setColorForeground(color(255, 100)) 30 | .showScrollbar(); 31 | 32 | codeTextarea.setText("// Text automagically generated"); 33 | 34 | checkbox = cp5.addCheckBox("checkBox") 35 | .setPosition(x + 40 + w * s + 10, y + 210) 36 | .setSize(20, 20) 37 | .setItemsPerRow(1) 38 | .addItem("inverted-subsequent LED rows", 0) 39 | ; 40 | 41 | buttonCopyText = cp5.addButton("copy text") 42 | .setValue(0) 43 | .setPosition(x + 40 + w * s + 10, y + 240) 44 | .setSize(200, 19) 45 | ; 46 | } 47 | 48 | UI (int _x, int _y) { 49 | x = _x; 50 | y= _y; 51 | mpix = new PIXEL_MATRIX(x + 20, y, ms, false); 52 | pix = new PIXEL_MATRIX(x + 20, y + 50, s, true); 53 | cp = new ColorPicker( x + 20 + w * s + 10, y + 50, 300, 200, 255 ); 54 | // UI elements related class 55 | codeTextarea = cp5.addTextarea("txt") 56 | .setPosition(x+20, y + h*s + 60) 57 | .setSize(400, 200) 58 | .setFont(createFont("courier", 12)) 59 | .setLineHeight(14) 60 | .setColor(color(128)) 61 | .setColorBackground(color(255, 100)) 62 | .setColorForeground(color(255, 100)) 63 | .showScrollbar(); 64 | 65 | codeTextarea.setText("// Text automagically generated"); 66 | 67 | checkbox = cp5.addCheckBox("checkBox") 68 | .setPosition(x + 20 + w * s + 10, y + 290) 69 | .setSize(20, 20) 70 | .setItemsPerRow(1) 71 | .setSpacingColumn(30) 72 | .setSpacingRow(20) 73 | .addItem("inverted-subsequent LED rows", 0) 74 | ; 75 | 76 | buttonCopyText = cp5.addButton("copy text") 77 | .setPosition(x + 20 + w * s + 10, y + 320) 78 | .setSize(200, 19) 79 | ; 80 | } 81 | 82 | // methods 83 | void update() { 84 | fill(0); 85 | textSize(50); 86 | text("PixelCrafter", x + 70, y + 35); 87 | textSize(20); 88 | text(ver, x + 350, y + 35); 89 | mpix.update(); 90 | pix.update(); 91 | cp.update(); 92 | 93 | // refresh the code 94 | codeTextarea.clear(); 95 | codeTextarea.setText(code); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/colorpicker.pde: -------------------------------------------------------------------------------- 1 | public class ColorPicker 2 | { 3 | int x, y, w, h; 4 | public int c; 5 | PImage cpImage; 6 | 7 | public ColorPicker ( int x, int y, int w, int h, int c ) 8 | { 9 | this.x = x; 10 | this.y = y; 11 | this.w = w; 12 | this.h = h; 13 | this.c = c; 14 | 15 | cpImage = new PImage( w, h ); 16 | 17 | init(); 18 | } 19 | 20 | private void init () 21 | { 22 | // draw color, the w-40 determines how much space is left from the right 23 | // the greybar is only 30px width, so the rest is left for the generator 24 | // to fill in 25 | int cw = w - 40; 26 | for ( int i=0; i> 16 & 0xFF; 55 | } 56 | 57 | private float iGreen(color c) { 58 | return c >> 8 & 0xFF; 59 | } 60 | 61 | private float iBlue(color c) { 62 | return c & 0xFF; 63 | } 64 | 65 | private void setGradient(int x, int y, float w, float h, int c1, int c2 ) 66 | { 67 | 68 | float deltaR = iRed(c2) - iRed(c1); 69 | float deltaG = iGreen(c2) - iGreen(c1); 70 | float deltaB = iBlue(c2) - iBlue(c1); 71 | 72 | for (int j = y; j<(y+h); j++) 73 | { 74 | int c = color( iRed(c1)+(j-y)*(deltaR/h), iGreen(c1)+(j-y)*(deltaG/h), iBlue(c1)+(j-y)*(deltaB/h) ); 75 | cpImage.set( x, j, c ); 76 | } 77 | } 78 | 79 | private void drawRect( int rx, int ry, int rw, int rh, int rc ) 80 | { 81 | for (int i=rx; i= x && 97 | mouseX < x + w && 98 | mouseY >= y && 99 | mouseY < y + h ) 100 | { 101 | c = get( mouseX, mouseY ); 102 | } 103 | 104 | // this is the color selection box 105 | // c should be made public so that other 106 | // classes can get the color, I implement a getter 107 | fill( c ); 108 | rect( x, y+h+10, 20, 20 ); 109 | } 110 | 111 | // the setter 112 | public void setColor(int _c) { 113 | c = _c; 114 | } 115 | 116 | // the getter 117 | public int getColor() { 118 | return c; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/data/AdvoCut.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/data/AdvoCut.ttf -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/data/head.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/data/head.gif -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/data/miepsfonts.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | Untitled Document 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
 
14 |
15 | 16 | 17 | 36 | 37 |
18 |

This Font was brought 19 | to you by miepsfonts, a division of homebrainbox, and is free for non-commercial 20 | use .

21 |

The included files 22 | must not be modified and this readme file must be included with each font. 23 | Fonts may not be included on any collections of public domain or shareware 24 | with out our expressed permission. For more information please visit our 25 | homepage :

26 |

www.homebrainbox.com

27 |

Or mail me:

28 |

mieps@homebrainbox.com

29 |

Thanks for your interest. 30 | Feel free to send me money, drugs, women or any kind of feedback.

31 |

mieps

32 |

Copyright © 2001 33 | Marc André Misman. All rights reserved.

34 |

 

35 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/mouse_and_keyboard.pde: -------------------------------------------------------------------------------- 1 | void mousePressed() { 2 | // if SHIFT is pressed, capture color, 3 | // if CONTROL is pressed, fill up with color 4 | // if no key is pressed, just draw 5 | if (keyPressed) { 6 | if (ui.pix.hover()) { 7 | if (keyCode == CONTROL) { 8 | //ui.pix.fillColor(ui.pix.pix[ui.pix.pixelOn()].px, ui.pix.pix[ui.pix.pixelOn()].py, ui.cp.getColor(), ui.pix.pix[ui.pix.pixelOn()].c); 9 | //ui.mpix.fillColor(ui.mpix.pix[ui.pix.pixelOn()].px, ui.mpix.pix[ui.pix.pixelOn()].py, ui.cp.getColor(), ui.mpix.pix[ui.pix.pixelOn()].c); 10 | } 11 | if (keyCode == SHIFT) 12 | ui.cp.setColor(ui.pix.pix[ui.pix.pixelOn()].c); 13 | } 14 | } else { 15 | if (ui.pix.hover()) { 16 | ui.pix.pix[ui.pix.pixelOn()].c = ui.cp.getColor(); 17 | ui.mpix.pix[ui.pix.pixelOn()].c = ui.cp.getColor(); 18 | } 19 | } 20 | } 21 | 22 | void mouseReleased() { 23 | // change text 24 | ui.code = ui.pix.generateCode(ui.outputMode); 25 | //XXX: ui.pix.sendToArduino(ui.outputMode); 26 | } 27 | 28 | void mouseDragged() { 29 | if (ui.pix.hover()) { 30 | ui.pix.pix[ui.pix.pixelOn()].c = ui.cp.getColor(); 31 | ui.mpix.pix[ui.pix.pixelOn()].c = ui.cp.getColor(); 32 | } 33 | } 34 | 35 | // capture events from the cp5 elements 36 | void controlEvent(ControlEvent theEvent) { 37 | if (theEvent.isFrom(ui.checkbox)) { 38 | // checkbox uses arrayValue to store the state of 39 | // individual checkbox-items. usage: 40 | println(ui.checkbox.getItem(0).getValue()); 41 | ui.outputMode = int(ui.checkbox.getItem(0).getValue()); 42 | } 43 | if (theEvent.isFrom(ui.buttonCopyText)) { 44 | print("copy text to clipboard"); 45 | GClip.copy(ui.codeTextarea.getText()); 46 | } 47 | } 48 | 49 | void sendMarker (int val) { 50 | myPort.write(val); 51 | println("sent marker: " + val); 52 | } 53 | 54 | void getMarker (int val) { 55 | println("got marker: " + val); 56 | } 57 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/PC2/pixelmatrix.pde: -------------------------------------------------------------------------------- 1 | class PIXEL_MATRIX { 2 | // vars 3 | int rows = 16; // width of the design box 4 | int columns = 16; // height of the design box 5 | int x = 0, y = 0; // coordinates 6 | int s = 25; // width and height of pixels 7 | boolean borderOn = false; // turn on or off the border of pixels 8 | 9 | public PIXEL[] pix = new PIXEL[rows*columns]; // array of pixels 10 | 11 | // constructor 12 | PIXEL_MATRIX () { 13 | initPixelMatrix(); 14 | } 15 | 16 | PIXEL_MATRIX (int _x, int _y) { 17 | x = _x; 18 | y = _y; 19 | initPixelMatrix(); 20 | } 21 | 22 | PIXEL_MATRIX (int _x, int _y, int _s) { 23 | x = _x; 24 | y = _y; 25 | s = _s; 26 | initPixelMatrix(); 27 | } 28 | 29 | PIXEL_MATRIX (int _x, int _y, int _s, boolean _borderOn) { 30 | x = _x; 31 | y = _y; 32 | s = _s; 33 | borderOn = _borderOn; 34 | initPixelMatrix(); 35 | } 36 | 37 | // methods 38 | void initPixelMatrix() { 39 | for (int i = 0; i < rows; i++) 40 | for (int j = 0; j < columns; j++) { 41 | pix[i*columns+j] = new PIXEL(0, 0, 0, j*s + x, i*s + y, s, borderOn); // pixels by default are dark grey 42 | pix[i*columns+j].px = j; 43 | pix[i*columns+j].py = i; 44 | } 45 | } 46 | 47 | void update() { 48 | for (int i = 0; i < rows; i++) 49 | for (int j = 0; j < columns; j++) 50 | pix[i*columns+j].update(); 51 | } 52 | 53 | public boolean hover() { 54 | boolean val = false; 55 | for (int i = 0; i < rows; i++) 56 | for (int j = 0; j < columns; j++) 57 | if (pix[i*columns+j].hover()) val = true; 58 | return val; 59 | } 60 | 61 | // return the number of the pixel being on 62 | public int pixelOn() { 63 | int val = -1; 64 | for (int i = 0; i < rows; i++) 65 | for (int j = 0; j < columns; j++) 66 | if (pix[i*columns+j].hover()) val = i*columns+j; 67 | return val; 68 | } 69 | 70 | // cc indicates current color, needed for recursion 71 | void fillColor(int _x, int _y, int _c, int cc) { 72 | // get the color of the pixel 73 | int pc = pix[_y*columns+_x].c; 74 | for (int i = -1; i <= 1; i++) { 75 | for (int j = -1; j <= 1; j++) { 76 | if (_x+i >= 0 && _x+i < columns && _y+j >= 0 && -y+j < rows) { 77 | if (i != 0 && j != 0) { 78 | fillColor(_x+i, _y+j, _c, pc); 79 | } else { 80 | if (cc == pc) { 81 | pix[_y*columns+_x].c = _c; 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | // method returning the code generated by the drawing 90 | String generateCode(int oM) { 91 | String code = ""; 92 | if (oM == 1) 93 | println("inverting every other line at output"); 94 | 95 | code = "byte red[] = {\n"; 96 | for (int i = 0; i < rows; i++) { 97 | for (int j = 0; j < columns; j++) { 98 | if (i%2 == 1 && oM == 1) 99 | code += int(map(red(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 100 | else 101 | code += int(map(red(pix[i*columns+j].c), 0, 255, 0, 100)); 102 | if (i*rows + j == columns*rows - 1) 103 | code += "};\n"; 104 | else 105 | if ((i*rows + j)%columns == 0 && i > 0) 106 | code += ",\n"; 107 | else 108 | code += ", "; 109 | } 110 | } 111 | 112 | code += "byte green[] = {\n"; 113 | for (int i = 0; i < rows; i++) { 114 | for (int j = 0; j < columns; j++) { 115 | if (i%2 == 1 && oM == 1) 116 | code += int(map(green(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 117 | else 118 | code += int(map(green(pix[i*columns+j].c), 0, 255, 0, 100)); 119 | if (i*rows + j == columns*rows - 1) 120 | code += "};\n"; 121 | else 122 | if ((i*rows + j)%columns == 0 && i > 0) 123 | code += ",\n"; 124 | else 125 | code += ", "; 126 | } 127 | } 128 | 129 | code += "byte blue[] = {\n"; 130 | for (int i = 0; i < rows; i++) { 131 | for (int j = 0; j < columns; j++) { 132 | if (i%2 == 1 && oM == 1) 133 | code += int(map(blue(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 134 | else 135 | code += int(map(blue(pix[i*columns+j].c), 0, 255, 0, 100)); 136 | if (i*rows + j == columns*rows - 1) 137 | code += "};\n"; 138 | else 139 | if ((i*rows + j)%columns == 0 && i > 0) 140 | code += ",\n"; 141 | else 142 | code += ", "; 143 | } 144 | } 145 | return code; 146 | } 147 | 148 | // send to Arduino 149 | void sendToArduino(int oM) { 150 | if (oM == 1) 151 | println("inverting every other line at output for serial"); 152 | 153 | // send initial marker 154 | sendMarker(255); 155 | 156 | // wait for Arduino to send an answer 157 | while (myPort.available() <= 0) { 158 | }; 159 | 160 | // loop until getting the final marker from Arduino 161 | int inByte = myPort.read(); 162 | getMarker(inByte); 163 | 164 | while (inByte != 254) { 165 | // wait for Arduino to send an answer 166 | while (myPort.available() <= 0) { 167 | }; 168 | inByte = myPort.read(); 169 | getMarker(inByte); 170 | 171 | // send red when requested 172 | if (inByte == 253) { 173 | // send marker 174 | sendMarker(253); 175 | 176 | // send red 177 | for (int i = 0; i < rows; i++) { 178 | for (int j = 0; j < columns; j++) { 179 | byte d = 0; 180 | if (i%2 == 1 && oM == 1) 181 | d = byte(map(red(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 182 | else 183 | d = byte(map(red(pix[i*columns + j].c), 0, 255, 0, 100)); 184 | myPort.write(d); 185 | } 186 | } 187 | } 188 | 189 | // send green when requested 190 | if (inByte == 252) { 191 | // send marker 192 | sendMarker(252); 193 | 194 | // send green 195 | for (int i = 0; i < rows; i++) { 196 | for (int j = 0; j < columns; j++) { 197 | byte d = 0; 198 | if (i%2 == 1 && oM == 1) 199 | d = byte(map(green(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 200 | else 201 | d = byte(map(green(pix[i*columns + j].c), 0, 255, 0, 100)); 202 | myPort.write(d); 203 | } 204 | } 205 | } 206 | 207 | // send blue when requested 208 | if (inByte == 251) { 209 | // send marker 210 | sendMarker(251); 211 | 212 | // send blue 213 | for (int i = 0; i < rows; i++) { 214 | for (int j = 0; j < columns; j++) { 215 | byte d = 0; 216 | if (i%2 == 1 && oM == 1) 217 | d = byte(map(blue(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 218 | else 219 | d = byte(map(blue(pix[i*columns + j].c), 0, 255, 0, 100)); 220 | myPort.write(d); 221 | } 222 | } 223 | } 224 | } 225 | // send closing marker 226 | sendMarker(254); 227 | } 228 | } 229 | 230 | class PIXEL { 231 | // vars 232 | int r = 200, g = 200, b = 200; // color 233 | color c = color(r, g, b); 234 | int s = 20; // size 235 | int x = 0, y = 0; // coordinates 236 | int px = 0, py = 0; // coordinates in the matrix (not pixels) 237 | boolean borderOn = false; // border to the pixels 238 | 239 | // constructor 240 | PIXEL () { 241 | } 242 | 243 | PIXEL (int _r, int _g, int _b) { 244 | r = _r; 245 | g = _g; 246 | b = _b; 247 | c = color(r, g, b); 248 | } 249 | 250 | PIXEL (int _r, int _g, int _b, int _x, int _y) { 251 | r = _r; 252 | g = _g; 253 | b = _b; 254 | c = color(r, g, b); 255 | x = _x; 256 | y = _y; 257 | } 258 | 259 | PIXEL (int _r, int _g, int _b, int _x, int _y, int _s) { 260 | r = _r; 261 | g = _g; 262 | b = _b; 263 | c = color(r, g, b); 264 | x = _x; 265 | y = _y; 266 | s = _s; 267 | } 268 | 269 | PIXEL (int _r, int _g, int _b, int _x, int _y, int _s, boolean _borderOn) { 270 | r = _r; 271 | g = _g; 272 | b = _b; 273 | c = color(r, g, b); 274 | x = _x; 275 | y = _y; 276 | s = _s; 277 | borderOn = _borderOn; 278 | } 279 | 280 | // methods 281 | void update() { 282 | if (borderOn) 283 | stroke(200); 284 | else 285 | noStroke(); 286 | fill(c); 287 | if (hover()) 288 | rect(x-2, y-2, s, s); 289 | else 290 | rect(x, y, s, s); 291 | } 292 | 293 | // interaction 294 | public boolean hover() { 295 | if (mouseX > x && mouseX < x + s && mouseY > y && mouseY < y + s) 296 | return true; 297 | return false; 298 | } 299 | 300 | // color setter 301 | public void setColor (int _c) { 302 | c = _c; 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/PixelCrafter/Readme.md: -------------------------------------------------------------------------------- 1 | # PixelCrafter v0002 alpha 2 | 3 | Processing sketch to help creating drawings on NeoPixel-based LED matrixes. 4 | 5 | Use the copy button to bring your drawing result into your Arduino sketch. 6 | 7 | ## Credits 8 | 9 | **Pixel Crafter v0002 alpha** 10 | 11 | *(c) 2018 David Cuartielless for Arduino* 12 | 13 | This code is licensed under GPLv3, feel free to use it and contribute to it via pull requests to this project 14 | 15 | * Uses ControlP5 for UI elements (but NOT color picker) 16 | * Uses color picker code as found on the Processing forum: https://forum.processing.org/one/topic/processing-color-picker.html 17 | * Uses AdvoCut font from Marc Andre Misman, (c) 2001 18 | * Clipboard code from: https://forum.processing.org/one/topic/copy-and-paste.html#25080000001711515.html 19 | 20 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/img/pixelcrafter_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 6 - LED matrix/img/pixelcrafter_window.png -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 6 - LED Matrix 2 | This example will allow you to modify your LED matrix with different arrays, and be able to turn it on/off with two buttons. 3 | 4 | 5 | 6 | ## Ingredients 7 | * Arduino UNO 8 | * LED Matrix (in this example a 16x16) 9 | * 2 buttons 10 | * Jumper wires 11 | 12 | 13 | ## Wiring 14 | 15 | *Connect the wires and components according to the fritzing below.* 16 | 17 | ![Fritzing diagram](realMatrix/episode6_fritzing.png "Fritzing diagram") 18 | 19 | ## PixelCrafter 20 | 21 | 22 | 23 | Modify the *ledData.h* file to represent whatever you want to using this Processing sketch. For using it you will need to: 24 | 25 | * install Processing from [https://processing.org] 26 | * double click on the *PC2.pde* file, what will open the sketch into the Processing IDE 27 | * click on the *play* button and start drawing 28 | * click on the *inverted-subsequent led rows* checkbox (this is needed because LED matrixes are like a long strip of LEDs where every other row is going from right to left 29 | * click on the *copy text* button to copy the code version of your drawing 30 | * paste the code in the *ledData.h* file, and upload it to your Arduino board 31 | 32 | ## Code 33 | 34 | ```sh 35 | /* 36 | NeoMatrix with two buttons 37 | Control a NeoPixel LED matrix using two buttons. 38 | The LED data is stored in arrays, allowing the generation of 39 | possible "screens" using external software 40 | (c) 2018 Karl, Josefine, and David for Arduino 41 | this code is GPLv3 42 | based on code by Shae Erisson (c) 2013 43 | */ 44 | 45 | #include 46 | #include "ledData.h" 47 | 48 | #ifdef __AVR__ 49 | #include 50 | #endif 51 | 52 | // NeoPixel string is connected to pin 6 53 | #define PIN 6 54 | 55 | // size of the LED matrix: 16x16 56 | #define NUMPIXELS 256 57 | 58 | // create the NeoPixel object 59 | Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); 60 | 61 | // variables to control the buttons 62 | // by default they have to be "HIGH" 63 | // because of using the internal pullup 64 | int buttonPin1 = 2; 65 | int buttonPin2 = 3; 66 | int buttonState1 = HIGH; 67 | int buttonState2 = HIGH; 68 | int buttonStateOld1 = HIGH; 69 | int buttonStateOld2 = HIGH; 70 | 71 | // see the other tab for checking 72 | // the arrays storing the LED data 73 | 74 | void setup() { 75 | // init the NeoPixel matrix 76 | pixels.begin(); 77 | 78 | // configure the buttons with internal pullup resistors 79 | pinMode(buttonPin1, INPUT_PULLUP); 80 | pinMode(buttonPin2, INPUT_PULLUP); 81 | } 82 | 83 | void loop() { 84 | // check the status of the buttons 85 | buttonState1 = digitalRead(buttonPin1); 86 | buttonState2 = digitalRead(buttonPin2); 87 | 88 | // if button 1 is pressed, load the image 89 | if (buttonState1 == LOW && buttonStateOld1 == HIGH) 90 | showImage(); 91 | 92 | // if button 2 is pressed, clear the image 93 | if (buttonState2 == LOW && buttonStateOld2 == HIGH) 94 | clearImage(); 95 | 96 | // update the button states 97 | buttonStateOld1 = buttonState1; 98 | buttonStateOld2 = buttonState2; 99 | } 100 | 101 | // send the color information to the screen taking the data 102 | // from the arrays declared at the beginning of the program 103 | void showImage() { 104 | for (int i = 0; i < NUMPIXELS; i++) 105 | pixels.setPixelColor(i, pixels.Color(red[i], green[i], blue[i])); 106 | 107 | pixels.show(); 108 | } 109 | 110 | // send a bunch of zeroes to the string 111 | void clearImage() { 112 | for (int i = 0; i < NUMPIXELS; i++) 113 | pixels.setPixelColor(i, pixels.Color(0, 0, 0)); 114 | 115 | pixels.show(); 116 | } 117 | ``` 118 | ## *IMPORTANT: You will also have to download the ledData.h file 119 | ## Start using 120 | 121 | After wiring and uploading the code, we can now start making our own 'pictures' on the LED matrix. What we need to modify is the ledData.h file, which contains 3 different arrays: red, green & blue. Each array has 256 numbers. For example, if we want to modify pixel number 35, we go to number 35 in the array, and write a value between 1-256 to set the brightness of it. 122 | 123 | In combination with this code, we can also use a tool call PixelCrafter, a Processing powered application where we can draw a picture with different colours, and then export it in the form of arrays. 124 | 125 | 126 | ## Outcome 127 | 128 | In this example we have gone through how an LED matrix works, and how arrays are used. We have also showed how we can call upon different functions and how we use an external file for data. 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/realMatrix/episode6_fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 6 - LED matrix/realMatrix/episode6_fritzing.png -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/realMatrix/ledData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ledData.h 3 | * 4 | * data to be loaded onto the LED matrix, note that it is 5 | * a weird Xmas tree, mostly because "the winter is coming" 6 | * 7 | */ 8 | 9 | int red[] = { 10 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40, 11 | 0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0, 12 | 0,40,0,0,0,0,0,100,100,100,0,0,0,0,0,0, 13 | 0,0,40,0,0,0,0,100,0,0,0,0,0,0,0,0, 14 | 0,0,0,40,0,0,0,0,100,0,0,0,0,0,0,0, 15 | 0,0,0,0,0,0,100,0,100,0,0,0,0,0,0,0, 16 | 0,0,0,0,0,0,100,0,0,0,100,0,0,0,0,0, 17 | 0,0,0,0,100,0,0,0,0,0,100,0,0,0,0,0, 18 | 0,0,0,0,0,100,0,0,0,0,0,100,0,0,0,0, 19 | 0,0,0,100,0,0,0,0,0,0,0,100,0,0,0,0, 20 | 0,0,0,0,100,0,0,0,0,0,0,0,100,0,0,0, 21 | 0,0,100,0,0,0,0,0,0,0,0,0,100,0,0,0, 22 | 0,0,0,100,0,0,0,0,0,0,0,0,0,100,0,0, 23 | 0,0,0,0,0,100,0,0,0,100,0,0,0,0,0,0, 24 | 0,0,0,0,0,0,100,0,0,0,100,0,0,0,0,0, 25 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 26 | }; 27 | 28 | int green[] = { 29 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40, 30 | 0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0, 31 | 0,40,0,0,0,0,0,100,100,100,0,0,0,0,0,0, 32 | 0,0,40,0,0,0,0,100,0,0,0,0,0,0,0,0, 33 | 0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0, 34 | 0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0, 35 | 0,0,0,0,0,0,0,100,100,100,0,0,0,0,0,0, 36 | 0,0,0,0,0,100,100,100,100,100,0,0,0,0,0,0, 37 | 0,0,0,0,0,0,100,100,100,100,100,0,0,0,0,0, 38 | 0,0,0,0,100,100,100,100,100,100,100,0,0,0,0,0, 39 | 0,0,0,0,0,100,100,100,100,100,100,100,0,0,0,0, 40 | 0,0,0,100,100,100,100,100,100,100,100,100,0,0,0,0, 41 | 0,0,0,0,100,100,100,100,100,100,100,100,100,0,0,0, 42 | 0,0,0,0,0,0,100,100,100,0,0,0,0,0,0,0, 43 | 0,0,0,0,0,0,0,100,100,100,0,0,0,0,0,0, 44 | 0,0,0,0,0,100,100,100,100,100,0,0,0,0,0,0, 45 | }; 46 | 47 | int blue[] = { 48 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40, 49 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 50 | 0,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0, 51 | 0,0,0,0,0,0,100,100,100,0,0,0,0,0,0,0, 52 | 0,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0, 53 | 0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0, 54 | 0,0,0,0,0,0,0,100,100,100,0,0,0,0,0,0, 55 | 0,0,0,0,0,100,100,100,100,100,0,0,0,0,0,0, 56 | 0,0,0,0,0,0,100,100,100,100,100,0,0,0,0,0, 57 | 0,0,0,0,100,100,100,100,100,100,100,0,0,0,0,0, 58 | 0,0,0,0,0,100,100,100,100,100,100,100,0,0,0,0, 59 | 0,0,0,100,100,100,100,100,100,100,100,100,0,0,0,0, 60 | 0,0,0,0,100,100,100,100,100,100,100,100,100,0,0,0, 61 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 62 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 63 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 64 | }; 65 | 66 | -------------------------------------------------------------------------------- /Season 2/Episode 6 - LED matrix/realMatrix/realMatrix.ino: -------------------------------------------------------------------------------- 1 | /* 2 | NeoMatrix with two buttons 3 | 4 | Control a NeoPixel LED matrix using two buttons. 5 | 6 | The LED data is stored in arrays, allowing the generation of 7 | possible "screens" using external software 8 | 9 | (c) 2018 Karl, Josefine, and David for Arduino 10 | this code is GPLv3 11 | 12 | based on code by Shae Erisson (c) 2013 13 | 14 | */ 15 | 16 | #include 17 | #include "ledData.h" 18 | 19 | #ifdef __AVR__ 20 | #include 21 | #endif 22 | 23 | // NeoPixel string is connected to pin 6 24 | #define PIN 6 25 | 26 | // size of the LED matrix: 16x16 27 | #define NUMPIXELS 256 28 | 29 | // create the NeoPixel object 30 | Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); 31 | 32 | // variables to control the buttons 33 | // by default they have to be "HIGH" 34 | // because of using the internal pullup 35 | int buttonPin1 = 2; 36 | int buttonPin2 = 3; 37 | int buttonState1 = HIGH; 38 | int buttonState2 = HIGH; 39 | int buttonStateOld1 = HIGH; 40 | int buttonStateOld2 = HIGH; 41 | 42 | // see the other tab for checking 43 | // the arrays storing the LED data 44 | 45 | void setup() { 46 | // init the NeoPixel matrix 47 | pixels.begin(); 48 | 49 | // configure the buttons with internal pullup resistors 50 | pinMode(buttonPin1, INPUT_PULLUP); 51 | pinMode(buttonPin2, INPUT_PULLUP); 52 | } 53 | 54 | void loop() { 55 | // check the status of the buttons 56 | buttonState1 = digitalRead(buttonPin1); 57 | buttonState2 = digitalRead(buttonPin2); 58 | 59 | // if button 1 is pressed, load the image 60 | if (buttonState1 == LOW && buttonStateOld1 == HIGH) 61 | showImage(); 62 | 63 | // if button 2 is pressed, clear the image 64 | if (buttonState2 == LOW && buttonStateOld2 == HIGH) 65 | clearImage(); 66 | 67 | // update the button states 68 | buttonStateOld1 = buttonState1; 69 | buttonStateOld2 = buttonState2; 70 | } 71 | 72 | // send the color information to the screen taking the data 73 | // from the arrays declared at the beginning of the program 74 | void showImage() { 75 | for (int i = 0; i < NUMPIXELS; i++) 76 | pixels.setPixelColor(i, pixels.Color(red[i], green[i], blue[i])); 77 | 78 | pixels.show(); 79 | } 80 | 81 | // send a bunch of zeroes to the string 82 | void clearImage() { 83 | for (int i = 0; i < NUMPIXELS; i++) 84 | pixels.setPixelColor(i, pixels.Color(0, 0, 0)); 85 | 86 | pixels.show(); 87 | } 88 | 89 | -------------------------------------------------------------------------------- /Season 2/Episode 7 - Temperature & Humidity display/DHT_LCD/DHT_LCD.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Digital Humidity & Temperature Sensor (DHT) 3 | that prints the values of the DHT on an 4 | LCD screen. 5 | 6 | (c) 2018 Karl, Josefine & David for Arduino 7 | 8 | based on code by ThothLoki (c) 2016 9 | 10 | */ 11 | 12 | #include 13 | #include "DHT.h" 14 | 15 | // set the DHT Pin 16 | #define DHTPIN 8 17 | 18 | //define LCD pins 19 | LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 20 | #define DHTTYPE DHT11 21 | DHT dht(DHTPIN, DHTTYPE); 22 | 23 | 24 | void setup() { 25 | //starts LCD 26 | lcd.begin(16, 2); 27 | //starts DHT 28 | dht.begin(); 29 | 30 | lcd.print("Temp: Humid:"); 31 | } 32 | 33 | void loop() { 34 | delay(500); 35 | 36 | //set location of where text will begin 37 | lcd.setCursor(0, 1); 38 | 39 | // reads humidity 40 | float h = dht.readHumidity(); 41 | 42 | //reads temperature (celsius) 43 | float c = dht.readTemperature(); 44 | 45 | //reads temperature (fahrenheit) 46 | float f = dht.readTemperature(true); 47 | 48 | 49 | if (isnan(h) || isnan(c)) { 50 | lcd.print("ERROR"); 51 | return; 52 | } 53 | //prints temperature. to display fahrenheit, replace 'c' with an 'f' 54 | lcd.print(c); 55 | lcd.setCursor(9,1); 56 | //prints humidity 57 | lcd.print(h); 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Season 2/Episode 7 - Temperature & Humidity display/DHT_LCD/episode7_fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 7 - Temperature & Humidity display/DHT_LCD/episode7_fritzing.png -------------------------------------------------------------------------------- /Season 2/Episode 7 - Temperature & Humidity display/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 7 - Temperature & Humidity display 2 | This example will measure the temperature and humidity of your surroundings and print it on an LCD display. 3 | 4 | 5 | ## Ingredients 6 | - Arduino UNO 7 | - 1x LCD displau 8 | - 1x DHT11 temperature & humidity sensor (3 pin) 9 | - Potentiometer 10 | - 1x 220 ohm resistor 11 | - Jumper wires 12 | 13 | 14 | ## Wiring 15 | *Connect the wires and components according to the fritzing below.* 16 | ![Fritzing diagram](DHT_LCD/episode7_fritzing.png "Fritzing diagram") 17 | 18 | 19 | 20 | ## Code 21 | 22 | ```sh 23 | 24 | /* 25 | Digital Humidity & Temperature Sensor (DHT) 26 | that prints the values of the DHT on an 27 | LCD screen. 28 | 29 | (c) 2018 Karl, Josefine & David for Arduino 30 | 31 | based on code by ThothLoki (c) 2016 32 | 33 | */ 34 | 35 | #include 36 | #include "DHT.h" 37 | 38 | // set the DHT Pin 39 | #define DHTPIN 8 40 | 41 | //define LCD pins 42 | LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 43 | #define DHTTYPE DHT11 44 | DHT dht(DHTPIN, DHTTYPE); 45 | 46 | 47 | void setup() { 48 | //starts LCD 49 | lcd.begin(16, 2); 50 | //starts DHT 51 | dht.begin(); 52 | 53 | lcd.print("Temp: Humid:"); 54 | } 55 | 56 | void loop() { 57 | delay(500); 58 | 59 | //set location of where text will begin 60 | lcd.setCursor(0, 1); 61 | 62 | // reads humidity 63 | float h = dht.readHumidity(); 64 | 65 | //reads temperature (celsius) 66 | float c = dht.readTemperature(); 67 | 68 | //reads temperature (fahrenheit) 69 | float f = dht.readTemperature(true); 70 | 71 | 72 | if (isnan(h) || isnan(c)) { 73 | lcd.print("ERROR"); 74 | return; 75 | } 76 | //prints temperature. to display fahrenheit, replace 'c' with an 'f' 77 | lcd.print(c); 78 | lcd.setCursor(9,1); 79 | //prints humidity 80 | lcd.print(h); 81 | 82 | 83 | } 84 | 85 | ``` 86 | 87 | ## Start using 88 | 89 | After wiring and uploading the code, we can now start tracking the temperature & humidity. The values of the sensor will be printed on the LCD screen, and will appear where you have set the cursor. 90 | For e.g. **lcd.setCursor(0, 1);** will be the upper left corner of the screen. We have in this example used a DHT module, but you can further on try it out with different sensors that you want to display on the LCD. 91 | 92 | 93 | ## Outcome 94 | 95 | This example shows how we can grab the value of a sensor, in this case temperature & humidity, and have it printed on an LCD display. You can also try out different types of sensor, for e.g. a photoresistor to measure light, see if a button is being pressed or not or perhaps using the UNO's gyroscope to display its positions on the LCD. By having a visual data representation we can easily measure our surroundings, and it is a good method to use if you are doing a portable device. 96 | 97 | 98 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/Matrix_BT/Matrix_BT.ino: -------------------------------------------------------------------------------- 1 | /* 2 | LED Matrix controlled through Bluetooth 3 | 4 | Control a NeoPixel LED matrix using a HC-06 5 | Bluetooth module. 6 | 7 | Using arrays generated by PixelCrafter, made by 8 | (c) David Cuartielles, 2018 we create different screens 9 | that can be triggered through Bluetooth. 10 | 11 | (c) 2018 Karl, Josefine, and David for Arduino 12 | this code is GPLv3 13 | 14 | based on code by Mayoogh Girish (c) 2016 15 | 16 | */ 17 | #include 18 | #include "ledData.h" 19 | 20 | 21 | #ifdef __AVR__ 22 | #include 23 | #endif 24 | #define PIN 6 25 | #define NUMPIXELS 256 26 | 27 | 28 | 29 | Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); 30 | 31 | //stores data 32 | char data = 0; 33 | 34 | void setup() { 35 | 36 | Serial.begin(9600); 37 | pixels.begin(); // This initializes the NeoPixel library. 38 | } 39 | 40 | void loop() { 41 | 42 | //check if we receive any data 43 | if (Serial.available() > 0) // Send data only when you receive data: 44 | { 45 | data = Serial.read(); //Read incoming value and stores into data 46 | Serial.print(data); //Prints value to serial monitor 47 | Serial.print("\n"); 48 | 49 | //if data equals 1 the 'showImage()' function will execute every 1 second 50 | if (data == '1') { 51 | showImage(); 52 | delay(1000); 53 | clearImage(); 54 | delay(1000); 55 | showImage(); 56 | delay(1000); 57 | clearImage(); 58 | delay(1000); 59 | showImage(); 60 | delay(1000); 61 | clearImage(); 62 | delay(1000); 63 | } 64 | 65 | //if data equals 2 the 'showImage2()' function will execute every 1 second 66 | else if (data == '2') { 67 | showImage2(); 68 | delay(1000); 69 | clearImage(); 70 | delay(1000); 71 | showImage2(); 72 | delay(1000); 73 | clearImage(); 74 | delay(1000); 75 | showImage2(); 76 | delay(1000); 77 | clearImage(); 78 | delay(1000); 79 | } 80 | 81 | //if data equals 3 the 'showImage3()' function will execute every 1 second 82 | else if (data == '3') { 83 | showImage3(); 84 | delay(1000); 85 | clearImage(); 86 | delay(1000); 87 | showImage3(); 88 | delay(1000); 89 | clearImage(); 90 | delay(1000); 91 | showImage3(); 92 | delay(1000); 93 | clearImage(); 94 | } 95 | } 96 | } 97 | 98 | 99 | void showImage() { 100 | for (int i = 0; i < NUMPIXELS; i++) { 101 | // since we are working with no external battery power, 102 | // we need to map the maximum values of the light intensity 103 | // to 100, to avoid taking too much current from the USB port 104 | byte red = map(palette[3 * ledPixels[i]], 0, 255, 0, 100); 105 | byte green = map(palette[3 * ledPixels[i] + 1], 0, 255, 0, 100); 106 | byte blue = map(palette[3 * ledPixels[i] + 2], 0, 255, 0, 100); 107 | pixels.setPixelColor(i, pixels.Color(red, green, blue)); 108 | } 109 | 110 | pixels.show(); 111 | } 112 | 113 | void showImage2() { 114 | for (int i = 0; i < NUMPIXELS; i++) { 115 | // since we are working with no external battery power, 116 | // we need to map the maximum values of the light intensity 117 | // to 100, to avoid taking too much current from the USB port 118 | byte red = map(palette2[3 * ledPixels2[i]], 0, 255, 0, 100); 119 | byte green = map(palette2[3 * ledPixels2[i] + 1], 0, 255, 0, 100); 120 | byte blue = map(palette2[3 * ledPixels2[i] + 2], 0, 255, 0, 100); 121 | pixels.setPixelColor(i, pixels.Color(red, green, blue)); 122 | } 123 | 124 | pixels.show(); 125 | } 126 | 127 | void showImage3() { 128 | for (int i = 0; i < NUMPIXELS; i++) { 129 | // since we are working with no external battery power, 130 | // we need to map the maximum values of the light intensity 131 | // to 100, to avoid taking too much current from the USB port 132 | byte red = map(palette3[3 * ledPixels3[i]], 0, 255, 0, 100); 133 | byte green = map(palette3[3 * ledPixels3[i] + 1], 0, 255, 0, 100); 134 | byte blue = map(palette3[3 * ledPixels3[i] + 2], 0, 255, 0, 100); 135 | pixels.setPixelColor(i, pixels.Color(red, green, blue)); 136 | } 137 | 138 | pixels.show(); 139 | } 140 | 141 | 142 | 143 | //Clears the LED matrix 144 | void clearImage() { 145 | for (int i = 0; i < NUMPIXELS; i++) 146 | pixels.setPixelColor(i, pixels.Color(0, 0, 0)); 147 | 148 | pixels.show(); 149 | } 150 | 151 | 152 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/Matrix_BT/ledData.h: -------------------------------------------------------------------------------- 1 | 2 | byte palette[] = { 3 | 0, 255, 0, 0, 0, 0 4 | }; 5 | 6 | byte palette2[] = { 7 | 0, 0, 255, 0, 0, 0 8 | }; 9 | 10 | byte palette3[] = { 11 | 0, 166, 184, 254, 251, 250, 0, 0, 0, 0, 0, 0, 12 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 19 | }; 20 | 21 | byte ledPixels[] = { 22 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 23 | 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 24 | 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 25 | 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 26 | 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 27 | 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 28 | 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 29 | 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 30 | 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31 | 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 32 | 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 33 | 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 34 | 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 35 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 36 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 37 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}; 38 | 39 | 40 | byte ledPixels2[] = { 41 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 42 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 43 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 44 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 45 | 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 31, 31, 31, 31, 31, 46 | 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 31, 31, 31, 31, 31, 31, 47 | 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, 31, 31, 48 | 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, 49 | 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 31, 31, 31, 31, 31, 50 | 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 31, 31, 31, 31, 51 | 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, 31, 31, 52 | 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, 53 | 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, 31, 31, 54 | 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, 55 | 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 31, 31, 31, 56 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}; 57 | 58 | 59 | byte ledPixels3[] = { 60 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 61 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 62 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 63 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 64 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 65 | 31, 31, 31, 0, 0, 0, 31, 31, 31, 31, 0, 0, 0, 31, 31, 31, 66 | 31, 31, 0, 0, 0, 0, 0, 31, 31, 0, 0, 0, 0, 0, 31, 31, 67 | 31, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 68 | 31, 0, 0, 31, 31, 31, 0, 0, 0, 0, 31, 31, 31, 0, 0, 31, 69 | 31, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 70 | 31, 31, 0, 0, 0, 0, 0, 31, 31, 0, 0, 0, 0, 0, 31, 31, 71 | 31, 31, 31, 0, 0, 0, 31, 31, 31, 31, 0, 0, 0, 31, 31, 31, 72 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 73 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 74 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 75 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}; 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/GClip.java: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the GUI for Processing library 3 | http://www.lagers.org.uk/g4p/index.html 4 | http://gui4processing.googlecode.com/svn/trunk/ 5 | 6 | Copyright (c) 2008-09 Peter Lager 7 | 8 | To use the clipboard in your code: 9 | // Copy to clipboard 10 | GClip.copy(n1); 11 | // Get clipboard contents into another string 12 | n2 = GClip.paste(); 13 | 14 | The actual code to create the clipbaord, copy and paste were 15 | taken taken from a similar GUI library Interfascia ALPHA 002 -- 16 | http://superstable.net/interfascia/ produced by Brenden Berg 17 | The main change is to provide static copy and paste methods to 18 | separate the clipboard logic from the component logic and provide 19 | global access. 20 | 21 | This library is free software; you can redistribute it and/or 22 | modify it under the terms of the GNU Lesser General Public 23 | License as published by the Free Software Foundation; either 24 | version 2.1 of the License, or (at your option) any later version. 25 | 26 | This library is distributed in the hope that it will be useful, 27 | but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29 | Lesser General Public License for more details. 30 | 31 | You should have received a copy of the GNU Lesser General 32 | Public License along with this library; if not, write to the 33 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 34 | Boston, MA 02111-1307 USA 35 | */ 36 | 37 | import java.awt.Toolkit; 38 | import java.awt.datatransfer.Clipboard; 39 | import java.awt.datatransfer.ClipboardOwner; 40 | import java.awt.datatransfer.DataFlavor; 41 | import java.awt.datatransfer.StringSelection; 42 | import java.awt.datatransfer.Transferable; 43 | 44 | /* 45 | * I wanted to implement copying and pasting to the clipboard using static 46 | * methods to simplify the sharing of a single clipboard over all classes. 47 | * The need to implement the ClipboardOwner interface requires an object so 48 | * this class creates an object the first time an attempt to copy or paste 49 | * is used. 50 | * 51 | * All methods are private except copy() and paste() - lostOwnership() 52 | * has to be public because of the Clipboard owner interface. 53 | * 54 | * @author Peter Lager 55 | * 56 | */ 57 | 58 | /** 59 | * This provides clipboard functionality for text and is currently only used by the 60 | * GTextField class. 61 | * 62 | * @author Peter Lager 63 | */ 64 | public class GClip implements ClipboardOwner { 65 | /** 66 | * Static reference to enforce singleton pattern 67 | */ 68 | private static GClip gclip = null; 69 | 70 | /** 71 | * Class attribute to reference the programs clipboard 72 | */ 73 | private Clipboard clipboard = null; 74 | 75 | /** 76 | * Copy a string to the clipboard 77 | * @param chars 78 | */ 79 | public static boolean copy(String chars) { 80 | if (gclip == null) 81 | gclip = new GClip(); 82 | return gclip.copyString(chars); 83 | } 84 | 85 | /** 86 | * Get a string from the clipboard 87 | * @return the string on the clipboard 88 | */ 89 | public static String paste() { 90 | if (gclip == null) 91 | gclip = new GClip(); 92 | return gclip.pasteString(); 93 | } 94 | 95 | /** 96 | * Ctor is private so clipboard is only created when a copy or paste is 97 | * attempted and one does not exist already. 98 | */ 99 | private GClip() { 100 | if (clipboard == null) { 101 | makeClipboardObject(); 102 | } 103 | } 104 | 105 | /** 106 | * If security permits use the system clipboard otherwise create 107 | * our own application clipboard. 108 | */ 109 | private void makeClipboardObject() { 110 | SecurityManager security = System.getSecurityManager(); 111 | if (security != null) { 112 | try { 113 | security.checkSystemClipboardAccess(); 114 | clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 115 | } 116 | catch (SecurityException e) { 117 | clipboard = new Clipboard("Application Clipboard"); 118 | } 119 | } 120 | else { 121 | try { 122 | clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 123 | } 124 | catch (Exception e) { 125 | // THIS IS DUMB - true but is there another way - I think not 126 | } 127 | } 128 | } 129 | 130 | /** 131 | * Copy a string to the clipboard. If the Clipboard has not been created 132 | * then create it. 133 | * @return true for a successful copy to clipboard 134 | */ 135 | private boolean copyString(String chars) { 136 | if (clipboard == null) 137 | makeClipboardObject(); 138 | if (clipboard != null) { 139 | StringSelection fieldContent = new StringSelection (chars); 140 | clipboard.setContents (fieldContent, this); 141 | return true; 142 | } 143 | return false; 144 | } 145 | 146 | /** 147 | * Gets a string from the clipboard. If there is no Clipboard 148 | * then create it. 149 | * @return 150 | */ 151 | private String pasteString() { 152 | // If there is no clipboard then there is nothing to paste 153 | if (clipboard == null) { 154 | makeClipboardObject(); 155 | return ""; 156 | } 157 | // We have a clipboard so get the string if we can 158 | Transferable clipboardContent = clipboard.getContents(this); 159 | if ((clipboardContent != null) && 160 | (clipboardContent.isDataFlavorSupported(DataFlavor.stringFlavor))) { 161 | try { 162 | String tempString; 163 | tempString = (String) clipboardContent.getTransferData(DataFlavor.stringFlavor); 164 | return tempString; 165 | } 166 | catch (Exception e) { 167 | e.printStackTrace (); 168 | } 169 | } 170 | return ""; 171 | } 172 | 173 | /** 174 | * Reqd by ClipboardOwner interface 175 | */ 176 | public void lostOwnership(Clipboard clipboard, Transferable contents) { 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/PC3.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Pixel Crafter v0003 3 | 4 | (c) 2018 David Cuartielless for Arduino 5 | 6 | Uses ControlP5 for UI elements (but NOT color picker) 7 | Uses color picker code as found on the Processing forum: https://forum.processing.org/one/topic/processing-color-picker.html 8 | Uses AdvoCut font from Marc Andre Misman, (c) 2001 9 | Clipboard code from: https://forum.processing.org/one/topic/copy-and-paste.html#25080000001711515.html 10 | */ 11 | 12 | import controlP5.*; 13 | import processing.serial.*; 14 | 15 | boolean serialOn = false; 16 | 17 | // UI elements that need to be declared here 18 | UI ui; 19 | ControlP5 cp5; 20 | PFont font; 21 | 22 | String ver = "v0003 alpha"; 23 | 24 | Serial myPort; 25 | 26 | void setup() { 27 | size( 800, 730 ); 28 | 29 | cp5 = new ControlP5(this); 30 | ui = new UI(30, 30); 31 | 32 | // make sure the checkboxes are activated upon boot 33 | ui.checkboxInvert.activate(0); 34 | ui.checkboxCompress.activate(0); 35 | 36 | // set default color to white 37 | ui.cp.setColor(color(255)); 38 | 39 | // font related code 40 | // Uncomment the following two lines to see the available fonts 41 | //String[] fontList = PFont.list(); 42 | //printArray(fontList); 43 | font = createFont("AdvoCut", 50); 44 | textFont(font); 45 | 46 | // include serial port 47 | if (serialOn) myPort = new Serial(this, "/dev/ttyACM0", 9600); 48 | } 49 | 50 | void draw() { 51 | background(200); 52 | ui.update(); 53 | } 54 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/UI.pde: -------------------------------------------------------------------------------- 1 | public class UI { 2 | // vars 3 | int x = 0, y = 0; // UI coordinates 4 | int w = 20, h = 20; // size of the pixel matrix in our self-made pixels 5 | int s = 20, ms = 2; // size of each pixel in dots 6 | PIXEL_MATRIX mpix; 7 | PIXEL_MATRIX pix; 8 | PALETTE palette; 9 | ColorPicker cp; 10 | Textarea codeTextarea; 11 | CheckBox checkboxInvert; 12 | CheckBox checkboxCompress; 13 | Button buttonCopyText; 14 | String code = ""; 15 | int outputMode = 0; // by default do not invert every other output array (0) 16 | // invert output with (1) 17 | // use compression (1 on bit 2) 18 | 19 | // constructor 20 | UI () { 21 | mpix = new PIXEL_MATRIX(x + 40, y + 10, ms); 22 | pix = new PIXEL_MATRIX(x + 40, y + 40, s); 23 | palette = new PALETTE(x + 40, y + 240, s); // XXX: figure out these default configuration 24 | cp = new ColorPicker( x + 40 + w * s + 10, y + 40, 200, 200, 255 ); 25 | // UI elements related class 26 | codeTextarea = cp5.addTextarea("txt") 27 | .setPosition(x+40, y + h*s + 50) 28 | .setSize(400, 200) 29 | .setFont(createFont("courier", 12)) 30 | .setLineHeight(14) 31 | .setColor(color(128)) 32 | .setColorBackground(color(255, 100)) 33 | .setColorForeground(color(255, 100)) 34 | .showScrollbar(); 35 | 36 | codeTextarea.setText("// Text automagically generated"); 37 | 38 | checkboxInvert = cp5.addCheckBox("checkBox invert") 39 | .setPosition(x + 40 + w * s + 10, y + 210) 40 | .setSize(20, 20) 41 | .setItemsPerRow(1) 42 | .addItem("inverted-subsequent LED rows", 0) 43 | ; 44 | 45 | checkboxCompress = cp5.addCheckBox("checkBox compress") 46 | .setPosition(x + 40 + w * s + 10, y + 240) 47 | .setSize(20, 20) 48 | .setItemsPerRow(1) 49 | .addItem("compress data, 4:2:2 format", 0) 50 | ; 51 | 52 | buttonCopyText = cp5.addButton("copy text") 53 | .setValue(0) 54 | .setPosition(x + 40 + w * s + 10, y + 270) 55 | .setSize(200, 19) 56 | ; 57 | } 58 | 59 | UI (int _x, int _y) { 60 | x = _x; 61 | y= _y; 62 | mpix = new PIXEL_MATRIX(x + 20, y, ms, false); 63 | pix = new PIXEL_MATRIX(x + 20, y + 50, s, true); 64 | palette = new PALETTE(x + 20 + w * s + 10, y + 290, s, true); 65 | cp = new ColorPicker( x + 20 + w * s + 10, y + 50, 320, 200, 255 ); 66 | // UI elements related class 67 | codeTextarea = cp5.addTextarea("txt") 68 | .setPosition(x+20, y + h*s + 60) 69 | .setSize(400, 200) 70 | .setFont(createFont("courier", 12)) 71 | .setLineHeight(14) 72 | .setColor(color(128)) 73 | .setColorBackground(color(255, 100)) 74 | .setColorForeground(color(255, 100)) 75 | .showScrollbar(); 76 | 77 | codeTextarea.setText("// Text automagically generated"); 78 | 79 | checkboxInvert = cp5.addCheckBox("checkBox invert") 80 | .setPosition(x + 20 + w * s + 10, y + 340) 81 | .setSize(20, 20) 82 | .setItemsPerRow(1) 83 | .setSpacingColumn(30) 84 | .setSpacingRow(20) 85 | .addItem("inverted-subsequent LED rows", 0) 86 | ; 87 | 88 | checkboxCompress = cp5.addCheckBox("checkBox compress") 89 | .setPosition(x + 20 + w * s + 10, y + 370) 90 | .setSize(20, 20) 91 | .setItemsPerRow(1) 92 | .setSpacingColumn(30) 93 | .setSpacingRow(20) 94 | .addItem("compress data, 4:2:2 format", 0) 95 | ; 96 | 97 | buttonCopyText = cp5.addButton("copy text") 98 | .setPosition(x + 20 + w * s + 10, y + 400) 99 | .setSize(200, 19) 100 | ; 101 | } 102 | 103 | // methods 104 | void update() { 105 | fill(0); 106 | textSize(50); 107 | text("PixelCrafter", x + 70, y + 35); 108 | textSize(20); 109 | text(ver, x + 350, y + 35); 110 | mpix.update(); 111 | pix.update(); 112 | palette.update(); 113 | cp.update(); 114 | 115 | // refresh the code 116 | codeTextarea.clear(); 117 | codeTextarea.setText(code); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/XXX_TO_DO.pde: -------------------------------------------------------------------------------- 1 | /* 2 | TODO: 3 | 4 | * revise the way the arrays are printed so that they end up as a block 5 | of bytes and not as a single array 6 | * add a limit to palette size (right now we are just trusting people will not go crazy 7 | 8 | */ 9 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/colorpicker.pde: -------------------------------------------------------------------------------- 1 | public class ColorPicker 2 | { 3 | int x, y, w, h; 4 | public int c; 5 | PImage cpImage; 6 | 7 | public ColorPicker ( int x, int y, int w, int h, int c ) 8 | { 9 | this.x = x; 10 | this.y = y; 11 | this.w = w; 12 | this.h = h; 13 | this.c = c; 14 | 15 | cpImage = new PImage( w, h ); 16 | 17 | init(); 18 | } 19 | 20 | private void init () 21 | { 22 | // draw color, the w-40 determines how much space is left from the right 23 | // the greybar is only 30px width, so the rest is left for the generator 24 | // to fill in 25 | int cw = w - 40; 26 | for ( int i=0; i> 16 & 0xFF; 55 | } 56 | 57 | private float iGreen(color c) { 58 | return c >> 8 & 0xFF; 59 | } 60 | 61 | private float iBlue(color c) { 62 | return c & 0xFF; 63 | } 64 | 65 | private void setGradient(int x, int y, float w, float h, int c1, int c2 ) 66 | { 67 | 68 | float deltaR = iRed(c2) - iRed(c1); 69 | float deltaG = iGreen(c2) - iGreen(c1); 70 | float deltaB = iBlue(c2) - iBlue(c1); 71 | 72 | for (int j = y; j<(y+h); j++) 73 | { 74 | int c = color( iRed(c1)+(j-y)*(deltaR/h), iGreen(c1)+(j-y)*(deltaG/h), iBlue(c1)+(j-y)*(deltaB/h) ); 75 | cpImage.set( x, j, c ); 76 | } 77 | } 78 | 79 | private void drawRect( int rx, int ry, int rw, int rh, int rc ) 80 | { 81 | for (int i=rx; i= x && 97 | mouseX < x + w && 98 | mouseY >= y && 99 | mouseY < y + h ) 100 | { 101 | c = get( mouseX, mouseY ); 102 | } 103 | 104 | // this is the color selection box 105 | // c should be made public so that other 106 | // classes can get the color, I implement a getter 107 | fill( c ); 108 | rect( x, y+h+10, 20, 20 ); 109 | } 110 | 111 | // the setter 112 | public void setColor(int _c) { 113 | c = _c; 114 | } 115 | 116 | // the getter 117 | public int getColor() { 118 | return c; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/data/AdvoCut.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 8 - Bluetooth Matrix Special/PC3/data/AdvoCut.ttf -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/data/head.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 8 - Bluetooth Matrix Special/PC3/data/head.gif -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/data/miepsfonts.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | Untitled Document 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
 
14 |
15 | 16 | 17 | 36 | 37 |
18 |

This Font was brought 19 | to you by miepsfonts, a division of homebrainbox, and is free for non-commercial 20 | use .

21 |

The included files 22 | must not be modified and this readme file must be included with each font. 23 | Fonts may not be included on any collections of public domain or shareware 24 | with out our expressed permission. For more information please visit our 25 | homepage :

26 |

www.homebrainbox.com

27 |

Or mail me:

28 |

mieps@homebrainbox.com

29 |

Thanks for your interest. 30 | Feel free to send me money, drugs, women or any kind of feedback.

31 |

mieps

32 |

Copyright © 2001 33 | Marc André Misman. All rights reserved.

34 |

 

35 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/mouse_and_keyboard.pde: -------------------------------------------------------------------------------- 1 | void mousePressed() { 2 | // if SHIFT is pressed, capture color, 3 | // if CONTROL is pressed, fill up with color 4 | // if no key is pressed, just draw 5 | if (keyPressed) { 6 | if (ui.pix.hover()) { 7 | if (keyCode == CONTROL) { 8 | //ui.pix.fillColor(ui.pix.pix[ui.pix.pixelOn()].px, ui.pix.pix[ui.pix.pixelOn()].py, ui.cp.getColor(), ui.pix.pix[ui.pix.pixelOn()].c); 9 | //ui.mpix.fillColor(ui.mpix.pix[ui.pix.pixelOn()].px, ui.mpix.pix[ui.pix.pixelOn()].py, ui.cp.getColor(), ui.mpix.pix[ui.pix.pixelOn()].c); 10 | } 11 | if (keyCode == SHIFT) 12 | ui.cp.setColor(ui.pix.pix[ui.pix.pixelOn()].c); 13 | } 14 | } else { 15 | // check matrix 16 | if (ui.pix.hover()) { 17 | updateColorMatrix(); 18 | } 19 | 20 | // check palette 21 | if (ui.palette.hover()) { 22 | updateColorPalette(); 23 | } 24 | } 25 | } 26 | 27 | void mouseReleased() { 28 | // change text 29 | ui.code = ""; 30 | 31 | // if using compressed mode, print the palette first 32 | if (ui.checkboxCompress.getItem(0).getValue() == 1) 33 | ui.code = ui.palette.getPalette() + "\n"; 34 | 35 | // update palette, just in case 36 | ui.pix.initPalette(ui.palette); 37 | 38 | // in any case add the actual pixel array 39 | ui.code += ui.pix.generateCode(ui.outputMode); 40 | 41 | //XXX: ui.pix.sendToArduino(ui.outputMode); 42 | } 43 | 44 | void mouseDragged() { 45 | // check matrix 46 | if (ui.pix.hover()) { 47 | updateColorMatrix(); 48 | } 49 | 50 | // check palette 51 | if (ui.palette.hover()) { 52 | updateColorPalette(); 53 | } 54 | } 55 | 56 | // updateColor is changing the matrixes and updating 57 | // the palette 58 | void updateColorMatrix() { 59 | // capture the current color 60 | color cc = ui.cp.getColor(); 61 | 62 | // update matrices 63 | ui.pix.pix[ui.pix.pixelOn()].c = cc; 64 | ui.mpix.pix[ui.pix.pixelOn()].c = cc; 65 | 66 | // update palette if the color is not in the palette 67 | if (ui.palette.indexOfPalette(cc) == -1) { 68 | ui.palette.setNewPaletteItem(cc); 69 | } 70 | } 71 | 72 | void updateColorPalette() { 73 | // get the color from the palette 74 | color cc = ui.palette.pix[ui.palette.pixelOn()].c; 75 | 76 | // update active color with the palette selection 77 | ui.cp.setColor(cc); 78 | } 79 | 80 | // capture events from the cp5 elements 81 | // checkboxes act as flags on outputMode 82 | void controlEvent(ControlEvent theEvent) { 83 | if (theEvent.isFrom(ui.checkboxInvert)) { 84 | // checkbox uses arrayValue to store the state of 85 | // individual checkbox-items. usage: 86 | println(ui.checkboxInvert.getItem(0).getValue()); 87 | ui.outputMode |= int(ui.checkboxInvert.getItem(0).getValue()); 88 | } 89 | if (theEvent.isFrom(ui.checkboxCompress)) { 90 | // checkbox uses arrayValue to store the state of 91 | // individual checkbox-items. usage: 92 | println(ui.checkboxCompress.getItem(0).getValue()); 93 | ui.outputMode |= 2 * int(ui.checkboxCompress.getItem(0).getValue()); 94 | } 95 | if (theEvent.isFrom(ui.buttonCopyText)) { 96 | print("copy text to clipboard"); 97 | GClip.copy(ui.codeTextarea.getText()); 98 | } 99 | } 100 | 101 | void sendMarker (int val) { 102 | myPort.write(val); 103 | println("sent marker: " + val); 104 | } 105 | 106 | void getMarker (int val) { 107 | println("got marker: " + val); 108 | } 109 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/palette.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Class to store the color schema of an image as 3 | a way to allow compressed arrays 4 | */ 5 | class PALETTE { 6 | int index = 0; // latest item in the list 7 | int rows = 2; 8 | int columns = 16; 9 | int x = 0, y = 0; 10 | int s = 25; // width and height of pixels 11 | boolean borderOn = false; // turn on or off the border of pixels 12 | int PALETTE_SIZE = columns*rows; 13 | 14 | public PIXEL[] pix = new PIXEL[PALETTE_SIZE]; // array of pixels 15 | 16 | // constructor 17 | PALETTE() { 18 | initPixelMatrix(); 19 | } 20 | 21 | PALETTE (int _x, int _y) { 22 | x = _x; 23 | y = _y; 24 | initPixelMatrix(); 25 | } 26 | 27 | PALETTE (int _x, int _y, int _s) { 28 | x = _x; 29 | y = _y; 30 | s = _s; 31 | initPixelMatrix(); 32 | } 33 | 34 | PALETTE (int _x, int _y, int _s, boolean _borderOn) { 35 | x = _x; 36 | y = _y; 37 | s = _s; 38 | borderOn = _borderOn; 39 | initPixelMatrix(); 40 | } 41 | 42 | // initializer 43 | // methods 44 | void initPixelMatrix() { 45 | for (int i = 0; i < rows; i++) 46 | for (int j = 0; j < columns; j++) { 47 | pix[i*columns+j] = new PIXEL(0, 0, 0, j*s + x, i*s + y, s, borderOn); // pixels by default are dark grey 48 | pix[i*columns+j].px = j; 49 | pix[i*columns+j].py = i; 50 | } 51 | } 52 | 53 | /* void initPixelMatrix() { 54 | for( int i = 0; i < PALETTE_SIZE; i++) 55 | pix[i] = new PIXEL(0, 0, 0); 56 | } 57 | */ 58 | 59 | // getters 60 | color getPaletteItem(int _i) { 61 | return pix[_i].c; 62 | } 63 | 64 | String getPalette() { 65 | String pal = "byte palette[] = {\n"; 66 | for (int i = 0; i < PALETTE_SIZE; i++) { 67 | pal += int(red(pix[i].c)) + ", "; 68 | pal += int(green(pix[i].c)) + ", "; 69 | pal += int(blue(pix[i].c)); 70 | if (i < PALETTE_SIZE - 1) 71 | pal += ", "; 72 | if ((i+1) % 4 == 0) { 73 | pal += "\n"; 74 | println(i); 75 | } 76 | } 77 | pal += "};\n"; 78 | return pal; 79 | } 80 | 81 | // renderer 82 | void update() { 83 | for (int i = 0; i < rows; i++) 84 | for (int j = 0; j < columns; j++) 85 | pix[i*columns+j].update(); 86 | } 87 | 88 | // is the mouse over? 89 | public boolean hover() { 90 | boolean val = false; 91 | for (int i = 0; i < rows; i++) 92 | for (int j = 0; j < columns; j++) 93 | if (pix[i*columns+j].hover()) val = true; 94 | return val; 95 | } 96 | 97 | // return the number of the pixel being on 98 | public int pixelOn() { 99 | int val = -1; 100 | for (int i = 0; i < rows; i++) 101 | for (int j = 0; j < columns; j++) 102 | if (pix[i*columns+j].hover()) val = i*columns+j; 103 | return val; 104 | } 105 | 106 | // setters 107 | void setPaletteItem(color _c) { 108 | pix[index].c = _c; 109 | } 110 | 111 | void setNewPaletteItem(color _c) { 112 | pix[index].c = _c; 113 | index++; 114 | } 115 | 116 | void setPaletteItem(int _i, color _c) { 117 | pix[_i].c = _c; 118 | } 119 | 120 | // checker 121 | int indexOfPalette(color _c) { 122 | int i = -1; 123 | for (int j = 0; j < PALETTE_SIZE; j++) 124 | if (pix[j].c == _c) 125 | i=j; 126 | return i; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/PC3/pixelmatrix.pde: -------------------------------------------------------------------------------- 1 | class PIXEL_MATRIX { 2 | // vars 3 | int rows = 16; // width of the design box 4 | int columns = 16; // height of the design box 5 | int x = 0, y = 0; // coordinates 6 | int s = 25; // width and height of pixels 7 | boolean borderOn = false; // turn on or off the border of pixels 8 | 9 | public PIXEL[] pix = new PIXEL[rows*columns]; // array of pixels 10 | public PALETTE palette = new PALETTE(); // palette with the colors 11 | 12 | // constructor 13 | PIXEL_MATRIX () { 14 | initPixelMatrix(); 15 | } 16 | 17 | PIXEL_MATRIX (int _x, int _y) { 18 | x = _x; 19 | y = _y; 20 | initPixelMatrix(); 21 | } 22 | 23 | PIXEL_MATRIX (int _x, int _y, int _s) { 24 | x = _x; 25 | y = _y; 26 | s = _s; 27 | initPixelMatrix(); 28 | } 29 | 30 | PIXEL_MATRIX (int _x, int _y, int _s, boolean _borderOn) { 31 | x = _x; 32 | y = _y; 33 | s = _s; 34 | borderOn = _borderOn; 35 | initPixelMatrix(); 36 | } 37 | 38 | // methods 39 | void initPixelMatrix() { 40 | for (int i = 0; i < rows; i++) 41 | for (int j = 0; j < columns; j++) { 42 | pix[i*columns+j] = new PIXEL(0, 0, 0, j*s + x, i*s + y, s, borderOn); // pixels by default are dark grey 43 | pix[i*columns+j].px = j; 44 | pix[i*columns+j].py = i; 45 | } 46 | } 47 | 48 | void update() { 49 | for (int i = 0; i < rows; i++) 50 | for (int j = 0; j < columns; j++) 51 | pix[i*columns+j].update(); 52 | } 53 | 54 | public boolean hover() { 55 | boolean val = false; 56 | for (int i = 0; i < rows; i++) 57 | for (int j = 0; j < columns; j++) 58 | if (pix[i*columns+j].hover()) val = true; 59 | return val; 60 | } 61 | 62 | // return the number of the pixel being on 63 | public int pixelOn() { 64 | int val = -1; 65 | for (int i = 0; i < rows; i++) 66 | for (int j = 0; j < columns; j++) 67 | if (pix[i*columns+j].hover()) val = i*columns+j; 68 | return val; 69 | } 70 | 71 | // cc indicates current color, needed for recursion 72 | void fillColor(int _x, int _y, int _c, int cc) { 73 | // get the color of the pixel 74 | int pc = pix[_y*columns+_x].c; 75 | for (int i = -1; i <= 1; i++) { 76 | for (int j = -1; j <= 1; j++) { 77 | if (_x+i >= 0 && _x+i < columns && _y+j >= 0 && -y+j < rows) { 78 | if (i != 0 && j != 0) { 79 | fillColor(_x+i, _y+j, _c, pc); 80 | } else { 81 | if (cc == pc) { 82 | pix[_y*columns+_x].c = _c; 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | // update the palette using one external 91 | void initPalette(PALETTE _p) { 92 | for (int i = 0; i < 32; i++) { 93 | palette.pix[i].c = _p.pix[i].c; 94 | } 95 | } 96 | 97 | // method returning the code generated by the drawing 98 | String generateCode(int oM) { 99 | String code = ""; 100 | int flagInvert = (oM & 0x01); 101 | int flagCompress = (oM >> 1 & 0x01); 102 | 103 | // check flags 104 | if ( flagInvert == 1) 105 | println("inverting every other line at output"); 106 | if ( flagCompress == 1) 107 | println("compressing image using palette"); 108 | 109 | if (flagCompress == 0) { 110 | code = generateFullArrays(flagInvert); 111 | } else { 112 | code = generateCompressedArray(flagInvert); 113 | } 114 | return code; 115 | } 116 | 117 | String generateCompressedArray(int oM) { 118 | String code = "byte ledPixels[] = {\n"; 119 | for (int i = 0; i < rows; i++) { 120 | for (int j = 0; j < columns; j++) { 121 | if (i%2 == 1 && oM == 1) { 122 | // int val = 0; 123 | // val += int(map(red(pix[i*columns + columns -1 - j].c), 0, 255, 0, 15)) << 4; 124 | // val += int(map(green(pix[i*columns + columns -1 - j].c), 0, 255, 0, 3)) << 2; 125 | // val += int(map(blue(pix[i*columns + columns -1 - j].c), 0, 255, 0, 3)); 126 | int val = palette.indexOfPalette(pix[i*columns + columns -1 - j].c); 127 | code += val; 128 | } 129 | else { 130 | // int val = 0; 131 | // val += int(map(red(pix[i*columns+j].c), 0, 255, 0, 15)) << 4; 132 | // val += int(map(green(pix[i*columns+j].c), 0, 255, 0, 3)) << 2; 133 | // val += int(map(blue(pix[i*columns+j].c), 0, 255, 0, 3)); 134 | int val = palette.indexOfPalette(pix[i*columns+j].c); 135 | code += val; 136 | } 137 | if (i*rows + j == columns*rows - 1) 138 | code += "};\n"; 139 | else 140 | if ((i*rows + j + 1)%columns == 0) 141 | code += ",\n"; 142 | else 143 | code += ", "; 144 | } 145 | } 146 | return code; 147 | } 148 | 149 | String generateFullArrays(int oM) { 150 | String code = "byte red[] = {\n"; 151 | for (int i = 0; i < rows; i++) { 152 | for (int j = 0; j < columns; j++) { 153 | if (i%2 == 1 && oM == 1) 154 | code += int(map(red(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 155 | else 156 | code += int(map(red(pix[i*columns+j].c), 0, 255, 0, 100)); 157 | if (i*rows + j == columns*rows - 1) 158 | code += "};\n"; 159 | else 160 | if ((i*rows + j + 1)%columns == 0) 161 | code += ",\n"; 162 | else 163 | code += ", "; 164 | } 165 | } 166 | 167 | code += "byte green[] = {\n"; 168 | for (int i = 0; i < rows; i++) { 169 | for (int j = 0; j < columns; j++) { 170 | if (i%2 == 1 && oM == 1) 171 | code += int(map(green(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 172 | else 173 | code += int(map(green(pix[i*columns+j].c), 0, 255, 0, 100)); 174 | if (i*rows + j == columns*rows - 1) 175 | code += "};\n"; 176 | else 177 | if ((i*rows + j + 1)%columns == 0) 178 | code += ",\n"; 179 | else 180 | code += ", "; 181 | } 182 | } 183 | 184 | code += "byte blue[] = {\n"; 185 | for (int i = 0; i < rows; i++) { 186 | for (int j = 0; j < columns; j++) { 187 | if (i%2 == 1 && oM == 1) 188 | code += int(map(blue(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 189 | else 190 | code += int(map(blue(pix[i*columns+j].c), 0, 255, 0, 100)); 191 | if (i*rows + j == columns*rows - 1) 192 | code += "};\n"; 193 | else 194 | if ((i*rows + j + 1)%columns == 0) 195 | code += ",\n"; 196 | else 197 | code += ", "; 198 | } 199 | } 200 | return code; 201 | } 202 | 203 | // send to Arduino 204 | void sendToArduino(int oM) { 205 | if (oM == 1) 206 | println("inverting every other line at output for serial"); 207 | 208 | // send initial marker 209 | sendMarker(255); 210 | 211 | // wait for Arduino to send an answer 212 | while (myPort.available() <= 0) { 213 | }; 214 | 215 | // loop until getting the final marker from Arduino 216 | int inByte = myPort.read(); 217 | getMarker(inByte); 218 | 219 | while (inByte != 254) { 220 | // wait for Arduino to send an answer 221 | while (myPort.available() <= 0) { 222 | }; 223 | inByte = myPort.read(); 224 | getMarker(inByte); 225 | 226 | // send red when requested 227 | if (inByte == 253) { 228 | // send marker 229 | sendMarker(253); 230 | 231 | // send red 232 | for (int i = 0; i < rows; i++) { 233 | for (int j = 0; j < columns; j++) { 234 | byte d = 0; 235 | if (i%2 == 1 && oM == 1) 236 | d = byte(map(red(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 237 | else 238 | d = byte(map(red(pix[i*columns + j].c), 0, 255, 0, 100)); 239 | myPort.write(d); 240 | } 241 | } 242 | } 243 | 244 | // send green when requested 245 | if (inByte == 252) { 246 | // send marker 247 | sendMarker(252); 248 | 249 | // send green 250 | for (int i = 0; i < rows; i++) { 251 | for (int j = 0; j < columns; j++) { 252 | byte d = 0; 253 | if (i%2 == 1 && oM == 1) 254 | d = byte(map(green(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 255 | else 256 | d = byte(map(green(pix[i*columns + j].c), 0, 255, 0, 100)); 257 | myPort.write(d); 258 | } 259 | } 260 | } 261 | 262 | // send blue when requested 263 | if (inByte == 251) { 264 | // send marker 265 | sendMarker(251); 266 | 267 | // send blue 268 | for (int i = 0; i < rows; i++) { 269 | for (int j = 0; j < columns; j++) { 270 | byte d = 0; 271 | if (i%2 == 1 && oM == 1) 272 | d = byte(map(blue(pix[i*columns + columns -1 - j].c), 0, 255, 0, 100)); 273 | else 274 | d = byte(map(blue(pix[i*columns + j].c), 0, 255, 0, 100)); 275 | myPort.write(d); 276 | } 277 | } 278 | } 279 | } 280 | // send closing marker 281 | sendMarker(254); 282 | } 283 | } 284 | 285 | class PIXEL { 286 | // vars 287 | int r = 200, g = 200, b = 200; // color 288 | color c = color(r, g, b); 289 | int s = 20; // size 290 | int x = 0, y = 0; // coordinates 291 | int px = 0, py = 0; // coordinates in the matrix (not pixels) 292 | boolean borderOn = false; // border to the pixels 293 | 294 | // constructor 295 | PIXEL () { 296 | } 297 | 298 | PIXEL (int _r, int _g, int _b) { 299 | r = _r; 300 | g = _g; 301 | b = _b; 302 | c = color(r, g, b); 303 | } 304 | 305 | PIXEL (int _r, int _g, int _b, int _x, int _y) { 306 | r = _r; 307 | g = _g; 308 | b = _b; 309 | c = color(r, g, b); 310 | x = _x; 311 | y = _y; 312 | } 313 | 314 | PIXEL (int _r, int _g, int _b, int _x, int _y, int _s) { 315 | r = _r; 316 | g = _g; 317 | b = _b; 318 | c = color(r, g, b); 319 | x = _x; 320 | y = _y; 321 | s = _s; 322 | } 323 | 324 | PIXEL (int _r, int _g, int _b, int _x, int _y, int _s, boolean _borderOn) { 325 | r = _r; 326 | g = _g; 327 | b = _b; 328 | c = color(r, g, b); 329 | x = _x; 330 | y = _y; 331 | s = _s; 332 | borderOn = _borderOn; 333 | } 334 | 335 | // methods 336 | void update() { 337 | if (borderOn) 338 | stroke(200); 339 | else 340 | noStroke(); 341 | fill(c); 342 | if (hover()) 343 | rect(x-2, y-2, s, s); 344 | else 345 | rect(x, y, s, s); 346 | } 347 | 348 | // interaction 349 | public boolean hover() { 350 | if (mouseX > x && mouseX < x + s && mouseY > y && mouseY < y + s) 351 | return true; 352 | return false; 353 | } 354 | 355 | // color setter 356 | public void setColor (int _c) { 357 | c = _c; 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/img/fritzing_episode8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 2/Episode 8 - Bluetooth Matrix Special/img/fritzing_episode8.png -------------------------------------------------------------------------------- /Season 2/Episode 8 - Bluetooth Matrix Special/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 8 - Bluetooth Matrix Special 2 | This example will show how we can control a LED matrix remotely through Bluetooth. With the help of PixelCrafter we can also draw whatever picture we want and have it appear on the LED matrix. 3 | 4 | 5 | ## Ingredients 6 | - Arduino UNO 7 | - 1x HC-06 Bluetooth module 8 | - 1x LED Matrix 9 | - Jumper wires 10 | - Bluetooth serial application 11 | 12 | 13 | ## Wiring 14 | *Connect the wires and components according to the fritzing below.* 15 | ![alt text](https://github.com/arduino/livecast/raw/master/Season%202/Episode%208%20-%20Bluetooth%20Matrix%20Special/img/fritzing_episode8.png "Logo Title Text 1") 16 | 17 | 18 | 19 | ## Code 20 | 21 | ```sh 22 | 23 | /* 24 | LED Matrix controlled through Bluetooth 25 | 26 | Control a NeoPixel LED matrix using a HC-06 27 | Bluetooth module. 28 | 29 | Using arrays generated by PixelCrafter, made by 30 | (c) David Cuartielles, 2018 we create different screens 31 | that can be triggered through Bluetooth. 32 | 33 | (c) 2018 Karl, Josefine, and David for Arduino 34 | this code is GPLv3 35 | 36 | based on code by Mayoogh Girish (c) 2016 37 | 38 | */ 39 | #include 40 | 41 | //includes the file we store the arrays in 42 | #include "ledData.h" 43 | 44 | 45 | #ifdef __AVR__ 46 | #include 47 | #endif 48 | #define PIN 6 49 | #define NUMPIXELS 256 50 | 51 | 52 | 53 | Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); 54 | 55 | //stores data 56 | char data = 0; 57 | 58 | void setup() { 59 | 60 | Serial.begin(9600); 61 | pixels.begin(); // This initializes the NeoPixel library. 62 | } 63 | 64 | void loop() { 65 | 66 | //check if we receive any data 67 | if (Serial.available() > 0) // Send data only when you receive data: 68 | { 69 | data = Serial.read(); //Read incoming value and stores into data 70 | Serial.print(data); //Prints value to serial monitor 71 | Serial.print("\n"); 72 | 73 | //if data equals 1 the 'showImage()' function will execute every 1 second 74 | if (data == '1') { 75 | showImage(); 76 | delay(1000); 77 | clearImage(); 78 | delay(1000); 79 | showImage(); 80 | delay(1000); 81 | clearImage(); 82 | delay(1000); 83 | showImage(); 84 | delay(1000); 85 | clearImage(); 86 | delay(1000); 87 | } 88 | 89 | //if data equals 2 the 'showImage2()' function will execute every 1 second 90 | else if (data == '2') { 91 | showImage2(); 92 | delay(1000); 93 | clearImage(); 94 | delay(1000); 95 | showImage2(); 96 | delay(1000); 97 | clearImage(); 98 | delay(1000); 99 | showImage2(); 100 | delay(1000); 101 | clearImage(); 102 | delay(1000); 103 | } 104 | 105 | //if data equals 3 the 'showImage3()' function will execute every 1 second 106 | else if (data == '3') { 107 | showImage3(); 108 | delay(1000); 109 | clearImage(); 110 | delay(1000); 111 | showImage3(); 112 | delay(1000); 113 | clearImage(); 114 | delay(1000); 115 | showImage3(); 116 | delay(1000); 117 | clearImage(); 118 | } 119 | } 120 | } 121 | 122 | 123 | void showImage() { 124 | for (int i = 0; i < NUMPIXELS; i++) { 125 | // since we are working with no external battery power, 126 | // we need to map the maximum values of the light intensity 127 | // to 100, to avoid taking too much current from the USB port 128 | byte red = map(palette[3 * ledPixels[i]], 0, 255, 0, 100); 129 | byte green = map(palette[3 * ledPixels[i] + 1], 0, 255, 0, 100); 130 | byte blue = map(palette[3 * ledPixels[i] + 2], 0, 255, 0, 100); 131 | pixels.setPixelColor(i, pixels.Color(red, green, blue)); 132 | } 133 | 134 | pixels.show(); 135 | } 136 | 137 | void showImage2() { 138 | for (int i = 0; i < NUMPIXELS; i++) { 139 | // since we are working with no external battery power, 140 | // we need to map the maximum values of the light intensity 141 | // to 100, to avoid taking too much current from the USB port 142 | byte red = map(palette2[3 * ledPixels2[i]], 0, 255, 0, 100); 143 | byte green = map(palette2[3 * ledPixels2[i] + 1], 0, 255, 0, 100); 144 | byte blue = map(palette2[3 * ledPixels2[i] + 2], 0, 255, 0, 100); 145 | pixels.setPixelColor(i, pixels.Color(red, green, blue)); 146 | } 147 | 148 | pixels.show(); 149 | } 150 | 151 | void showImage3() { 152 | for (int i = 0; i < NUMPIXELS; i++) { 153 | // since we are working with no external battery power, 154 | // we need to map the maximum values of the light intensity 155 | // to 100, to avoid taking too much current from the USB port 156 | byte red = map(palette3[3 * ledPixels3[i]], 0, 255, 0, 100); 157 | byte green = map(palette3[3 * ledPixels3[i] + 1], 0, 255, 0, 100); 158 | byte blue = map(palette3[3 * ledPixels3[i] + 2], 0, 255, 0, 100); 159 | pixels.setPixelColor(i, pixels.Color(red, green, blue)); 160 | } 161 | 162 | pixels.show(); 163 | } 164 | 165 | 166 | 167 | //Clears the LED matrix 168 | void clearImage() { 169 | for (int i = 0; i < NUMPIXELS; i++) 170 | pixels.setPixelColor(i, pixels.Color(0, 0, 0)); 171 | 172 | pixels.show(); 173 | } 174 | 175 | 176 | 177 | ``` 178 | ## (!) Make sure to include the ledData.h file where we have stored the arrays 179 | ## Start using 180 | 181 | After wiring and uploading the code, we now need to connect to the HC-06 module. Using a Bluetooth Serial Terminal app such as [this one](https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal&hl=en), we can now send commands to the Arduino through Bluetooth using our phone. In the code we have if statements that will trigger a certain picture on the LED matrix, depending on what number comes into the Arduino. If it receives for e.g. a "1" it will trigger showImage(), "2" will trigger showImage2() and so on. 182 | 183 | 184 | ## Outcome 185 | 186 | This is a very good example on how both use a LED matrix innovatively and how we can make a remote Arduino project. By making it wireless, the Arduino can be used anywhere within range of the Bluetooth. 187 | 188 | 189 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC/WiFi_RTC.ino: -------------------------------------------------------------------------------- 1 | /* 2 | MKR1000 - MKR WiFi 1010 - MKR VIDOR 4000 WiFi RTC 3 | 4 | This sketch asks NTP for the Linux epoch and sets the internal Arduino MKR1000's RTC accordingly. 5 | 6 | created 08 Jan 2016 7 | by Arturo Guadalupi 8 | 9 | modified 26 Sept 2018 10 | 11 | http://arduino.cc/en/Tutorial/WiFiRTC 12 | This code is in the public domain. 13 | */ 14 | 15 | #include 16 | //#include 17 | #include //Include this instead of WiFi101.h as needed 18 | #include 19 | #include 20 | 21 | RTCZero rtc; 22 | 23 | #include "arduino_secrets.h" 24 | ///////please enter your sensitive data in the Secret tab/arduino_secrets.h 25 | char ssid[] = SECRET_SSID; // your network SSID (name) 26 | char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) 27 | int keyIndex = 0; // your network key Index number (needed only for WEP) 28 | 29 | int status = WL_IDLE_STATUS; 30 | 31 | const int GMT = 2; //change this to adapt it to your time zone 32 | 33 | void setup() { 34 | Serial.begin(115200); 35 | 36 | // check if the WiFi module works 37 | if (WiFi.status() == WL_NO_SHIELD) { 38 | Serial.println("WiFi shield not present"); 39 | // don't continue: 40 | while (true); 41 | } 42 | 43 | // attempt to connect to WiFi network: 44 | while ( status != WL_CONNECTED) { 45 | Serial.print("Attempting to connect to SSID: "); 46 | Serial.println(ssid); 47 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 48 | status = WiFi.begin(ssid, pass); 49 | 50 | // wait 10 seconds for connection: 51 | delay(10000); 52 | } 53 | 54 | // you're connected now, so print out the status: 55 | printWiFiStatus(); 56 | 57 | rtc.begin(); 58 | 59 | unsigned long epoch; 60 | int numberOfTries = 0, maxTries = 6; 61 | do { 62 | epoch = WiFi.getTime(); 63 | numberOfTries++; 64 | } 65 | while ((epoch == 0) && (numberOfTries < maxTries)); 66 | 67 | if (numberOfTries > maxTries) { 68 | Serial.print("NTP unreachable!!"); 69 | while (1); 70 | } 71 | else { 72 | Serial.print("Epoch received: "); 73 | Serial.println(epoch); 74 | rtc.setEpoch(epoch); 75 | 76 | Serial.println(); 77 | } 78 | } 79 | 80 | void loop() { 81 | printDate(); 82 | printTime(); 83 | Serial.println(); 84 | delay(1000); 85 | } 86 | 87 | void printTime() 88 | { 89 | print2digits(rtc.getHours() + GMT); 90 | Serial.print(":"); 91 | print2digits(rtc.getMinutes()); 92 | Serial.print(":"); 93 | print2digits(rtc.getSeconds()); 94 | Serial.println(); 95 | } 96 | 97 | void printDate() 98 | { 99 | Serial.print(rtc.getDay()); 100 | Serial.print("/"); 101 | Serial.print(rtc.getMonth()); 102 | Serial.print("/"); 103 | Serial.print(rtc.getYear()); 104 | 105 | Serial.print(" "); 106 | } 107 | 108 | 109 | void printWiFiStatus() { 110 | // print the SSID of the network you're attached to: 111 | Serial.print("SSID: "); 112 | Serial.println(WiFi.SSID()); 113 | 114 | // print your WiFi shield's IP address: 115 | IPAddress ip = WiFi.localIP(); 116 | Serial.print("IP Address: "); 117 | Serial.println(ip); 118 | 119 | // print the received signal strength: 120 | long rssi = WiFi.RSSI(); 121 | Serial.print("signal strength (RSSI):"); 122 | Serial.print(rssi); 123 | Serial.println(" dBm"); 124 | } 125 | 126 | void print2digits(int number) { 127 | if (number < 10) { 128 | Serial.print("0"); 129 | } 130 | Serial.print(number); 131 | } 132 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_SSID "ssid" 2 | #define SECRET_PASS "pass" 3 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC_revised/WiFi_RTC_revised.ino: -------------------------------------------------------------------------------- 1 | /* 2 | MKR 1010 / 1000 RTC over WiFi 3 | 4 | This sketch asks NTP for the Linux epoch and sets the internal Arduino MKR1000's RTC accordingly. 5 | 6 | created 08 Jan 2016 7 | by Arturo Guadalupi 8 | 9 | modified 26 Sept 2018 10 | 11 | revised 07 Jan 2019 12 | by D. Cuartielles 13 | 14 | based on: 15 | http://arduino.cc/en/Tutorial/WiFiRTC 16 | This code is in the public domain. 17 | */ 18 | 19 | #include 20 | //#include 21 | #include //Include this instead of WiFi101.h as needed 22 | #include 23 | #include 24 | 25 | RTCZero rtc; 26 | 27 | #include "arduino_secrets.h" 28 | ///////please enter your sensitive data in the Secret tab/arduino_secrets.h 29 | char ssid[] = SECRET_SSID; // your network SSID (name) 30 | char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) 31 | int keyIndex = 0; // your network key Index number (needed only for WEP) 32 | 33 | int status = WL_IDLE_STATUS; 34 | 35 | const int GMT = 2; //change this to adapt it to your time zone 36 | 37 | void setup() { 38 | Serial.begin(115200); 39 | 40 | configNetwork(); 41 | 42 | configRTC(); 43 | } 44 | 45 | void loop() { 46 | printDate(); 47 | printTime(); 48 | Serial.println(); 49 | delay(1000); 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC_revised/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_SSID "ssid" 2 | #define SECRET_PASS "pass" 3 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC_revised/functions.ino: -------------------------------------------------------------------------------- 1 | void configNetwork () { 2 | // check if the WiFi module works 3 | if (WiFi.status() == WL_NO_SHIELD) { 4 | Serial.println("WiFi shield not present"); 5 | // don't continue: 6 | while (true); 7 | } 8 | 9 | // attempt to connect to WiFi network: 10 | while ( status != WL_CONNECTED) { 11 | Serial.print("Attempting to connect to SSID: "); 12 | Serial.println(ssid); 13 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 14 | status = WiFi.begin(ssid, pass); 15 | 16 | // wait 10 seconds for connection: 17 | delay(10000); 18 | } 19 | 20 | // you're connected now, so print out the status: 21 | printWiFiStatus(); 22 | } 23 | 24 | void configRTC () { 25 | rtc.begin(); 26 | 27 | unsigned long epoch; 28 | int numberOfTries = 0, maxTries = 6; 29 | do { 30 | epoch = WiFi.getTime(); 31 | numberOfTries++; 32 | } 33 | while ((epoch == 0) && (numberOfTries < maxTries)); 34 | 35 | if (numberOfTries > maxTries) { 36 | Serial.print("NTP unreachable!!"); 37 | while (1); 38 | } 39 | else { 40 | Serial.print("Epoch received: "); 41 | Serial.println(epoch); 42 | rtc.setEpoch(epoch); 43 | 44 | Serial.println(); 45 | } 46 | } 47 | 48 | void printTime() 49 | { 50 | print2digits(rtc.getHours() + GMT); 51 | Serial.print(":"); 52 | print2digits(rtc.getMinutes()); 53 | Serial.print(":"); 54 | print2digits(rtc.getSeconds()); 55 | Serial.println(); 56 | } 57 | 58 | void printDate() 59 | { 60 | Serial.print(rtc.getDay()); 61 | Serial.print("/"); 62 | Serial.print(rtc.getMonth()); 63 | Serial.print("/"); 64 | Serial.print(rtc.getYear()); 65 | 66 | Serial.print(" "); 67 | } 68 | 69 | 70 | void printWiFiStatus() { 71 | // print the SSID of the network you're attached to: 72 | Serial.print("SSID: "); 73 | Serial.println(WiFi.SSID()); 74 | 75 | // print your WiFi shield's IP address: 76 | IPAddress ip = WiFi.localIP(); 77 | Serial.print("IP Address: "); 78 | Serial.println(ip); 79 | 80 | // print the received signal strength: 81 | long rssi = WiFi.RSSI(); 82 | Serial.print("signal strength (RSSI):"); 83 | Serial.print(rssi); 84 | Serial.println(" dBm"); 85 | } 86 | 87 | void print2digits(int number) { 88 | if (number < 10) { 89 | Serial.print("0"); 90 | } 91 | Serial.print(number); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC_screen/WiFi_RTC_screen.ino: -------------------------------------------------------------------------------- 1 | /* 2 | MKR 1010 / 1000 RTC over WiFi 3 | 4 | This sketch asks NTP for the Linux epoch and sets the internal Arduino MKR1000's RTC accordingly. 5 | It then displays it on a TFT screen minimizing the flickering 6 | 7 | created 07 Jan 2019 8 | by D. Cuartielles 9 | 10 | based on: 11 | http://arduino.cc/en/Tutorial/WiFiRTC 12 | 2016 by A. Guadalupi for Arduino 13 | graphicstest for the ILI9341 14 | by Limor Fried/Ladyada for Adafruit Industries 15 | 16 | This code is in the public domain. 17 | 18 | */ 19 | 20 | #include 21 | //#include 22 | #include //Include this instead of WiFi101.h as needed 23 | #include 24 | #include 25 | 26 | // includes for screen 27 | #include "Adafruit_GFX.h" 28 | #include "Adafruit_ILI9341.h" 29 | 30 | // includes for local info 31 | ///////please enter your sensitive data in the Secret tab/arduino_secrets.h 32 | #include "arduino_secrets.h" 33 | 34 | // screen pins (to display data) 35 | #define TFT_DC 7 36 | #define TFT_CS 5 37 | #define TFT_MOSI 8 38 | #define TFT_CLK 9 39 | #define TFT_RST 6 40 | #define TFT_MISO 10 41 | 42 | // data modes 43 | #define BOTH 1 44 | #define SERIAL 2 45 | #define SCREEN 3 46 | 47 | RTCZero rtc; 48 | Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO); 49 | 50 | char ssid[] = SECRET_SSID; // your network SSID (name) 51 | char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) 52 | int keyIndex = 0; // your network key Index number (needed only for WEP) 53 | 54 | int status = WL_IDLE_STATUS; 55 | 56 | long timer = 0; 57 | byte prevTime[] = {0, 0, 0}; 58 | byte currTime[] = {0, 0, 0}; 59 | 60 | const int GMT = 1; //change this to adapt it to your time zone 61 | 62 | // Initialize the Wifi client library 63 | WiFiClient client; 64 | 65 | // server address: 66 | char server[] = "cuartielles.com"; 67 | 68 | unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds 69 | const unsigned long postingInterval = 60L * 1000L; // delay between updates, in milliseconds 70 | 71 | void setup() { 72 | Serial.begin(115200); 73 | 74 | configDisplay(); 75 | 76 | tft.fillScreen(ILI9341_BLACK); 77 | 78 | configNetwork(BOTH); 79 | 80 | configRTC(BOTH); 81 | 82 | delay(5000); 83 | 84 | tft.fillScreen(ILI9341_BLACK); 85 | 86 | timer = millis(); // init time ticker 87 | } 88 | 89 | void loop() { 90 | getCurrentTime(); 91 | 92 | if (isDifferentTime()) 93 | timeToDisplay(BOTH); 94 | 95 | // if there is data coming in from the server, print it 96 | while (client.available()) { 97 | char c = client.read(); 98 | Serial.write(c); 99 | tft.print(c); 100 | } 101 | 102 | // if XX seconds have passed since your last connection, 103 | // then connect again and send data: 104 | if (millis() - lastConnectionTime > postingInterval) { 105 | httpRequest(BOTH); 106 | } 107 | 108 | copyTime(); 109 | } 110 | 111 | 112 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC_screen/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_SSID "ssid" 2 | #define SECRET_PASS "pass" 3 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC_screen/functions.ino: -------------------------------------------------------------------------------- 1 | void configNetwork (int mode) { 2 | // check if the WiFi module works 3 | if (WiFi.status() == WL_NO_SHIELD) { 4 | Serial.println("WiFi shield not present"); 5 | if (mode == SCREEN || BOTH) tft.println("WiFi shield not present"); 6 | // don't continue: 7 | while (true); 8 | } 9 | 10 | // attempt to connect to WiFi network: 11 | while ( status != WL_CONNECTED) { 12 | Serial.print("Attempting to connect to SSID: "); 13 | if (mode == SCREEN || BOTH) tft.print("Attempting to connect to SSID: "); 14 | Serial.println(ssid); 15 | if (mode == SCREEN || BOTH) tft.println(ssid); 16 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 17 | status = WiFi.begin(ssid, pass); 18 | 19 | // wait 10 seconds for connection: 20 | delay(10000); 21 | } 22 | 23 | // you're connected now, so print out the status: 24 | printWiFiStatus(mode); 25 | } 26 | 27 | void configRTC (int mode) { 28 | rtc.begin(); 29 | 30 | unsigned long epoch; 31 | int numberOfTries = 0, maxTries = 6; 32 | do { 33 | epoch = WiFi.getTime(); 34 | numberOfTries++; 35 | } 36 | while ((epoch == 0) && (numberOfTries < maxTries)); 37 | 38 | if (numberOfTries > maxTries) { 39 | Serial.print("NTP unreachable!!"); 40 | if (mode == SCREEN || BOTH) tft.print("NTP unreachable!!"); 41 | while (1); 42 | } 43 | else { 44 | Serial.print("Epoch received: "); 45 | if (mode == SCREEN || BOTH) tft.print("Epoch received: "); 46 | Serial.println(epoch); 47 | if (mode == SCREEN || BOTH) tft.println(epoch); 48 | rtc.setEpoch(epoch); 49 | 50 | Serial.println(); 51 | } 52 | } 53 | 54 | void configDisplay () { 55 | tft.begin(); 56 | 57 | // read diagnostics (optional but can help debug problems) 58 | uint8_t x = tft.readcommand8(ILI9341_RDMODE); 59 | Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX); 60 | x = tft.readcommand8(ILI9341_RDMADCTL); 61 | Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX); 62 | x = tft.readcommand8(ILI9341_RDPIXFMT); 63 | Serial.print("Pixel Format: 0x"); Serial.println(x, HEX); 64 | x = tft.readcommand8(ILI9341_RDIMGFMT); 65 | Serial.print("Image Format: 0x"); Serial.println(x, HEX); 66 | x = tft.readcommand8(ILI9341_RDSELFDIAG); 67 | Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 68 | 69 | tft.setRotation(3); // to place the screen image in the expected direction 70 | } 71 | 72 | void printTime(int mode, boolean current = true) 73 | { 74 | if (current) print2digits(currTime[0] + GMT, mode); 75 | else print2digits(prevTime[0] + GMT, mode); 76 | 77 | if (mode == SERIAL || mode == BOTH) Serial.print(":"); 78 | if (mode == SCREEN || mode == BOTH) tft.print(":"); 79 | 80 | if (current) print2digits(currTime[1], mode); 81 | else print2digits(prevTime[1], mode); 82 | 83 | if (mode == SERIAL || mode == BOTH) Serial.print(":"); 84 | if (mode == SCREEN || mode == BOTH) tft.print(":"); 85 | 86 | if (current) print2digits(currTime[2], mode); 87 | else print2digits(prevTime[2], mode); 88 | 89 | if (mode == SERIAL || mode == BOTH) Serial.println(); 90 | if (mode == SCREEN || mode == BOTH) tft.println(); 91 | } 92 | 93 | void deleteTime(int mode, boolean current = true, int howDiff = -1) 94 | { 95 | if (current) print2digits(currTime[0] + GMT, mode); 96 | else if (howDiff == 0) 97 | print2digits(prevTime[0] + GMT, mode); 98 | else tft.print(" "); 99 | 100 | if (mode == SERIAL || mode == BOTH) Serial.print(":"); 101 | if (mode == SCREEN || mode == BOTH) tft.print(":"); 102 | 103 | if (current) print2digits(currTime[1], mode); 104 | else if (howDiff == 0 || howDiff == 1) 105 | print2digits(prevTime[1], mode); 106 | else tft.print(" "); 107 | 108 | if (mode == SERIAL || mode == BOTH) Serial.print(":"); 109 | if (mode == SCREEN || mode == BOTH) tft.print(":"); 110 | 111 | if (current) print2digits(currTime[2], mode); 112 | else if (howDiff != -1) 113 | print2digits(prevTime[2], mode); 114 | 115 | if (mode == SERIAL || mode == BOTH) Serial.println(); 116 | if (mode == SCREEN || mode == BOTH) tft.println(); 117 | } 118 | 119 | void printDate(int mode) 120 | { 121 | if (mode == SERIAL || mode == BOTH) { 122 | Serial.print(rtc.getDay()); 123 | Serial.print("/"); 124 | Serial.print(rtc.getMonth()); 125 | Serial.print("/"); 126 | Serial.print(rtc.getYear()); 127 | 128 | Serial.print(" "); 129 | } 130 | 131 | if (mode == SCREEN || mode == BOTH) { 132 | tft.print(rtc.getDay()); 133 | tft.print("/"); 134 | tft.print(rtc.getMonth()); 135 | tft.print("/"); 136 | tft.println(rtc.getYear()); 137 | } 138 | } 139 | 140 | 141 | void printWiFiStatus(int mode) { 142 | // print the SSID of the network you're attached to: 143 | Serial.print("SSID: "); 144 | if (mode == SCREEN || mode == BOTH) tft.print("SSID: "); 145 | Serial.println(WiFi.SSID()); 146 | if (mode == SCREEN || mode == BOTH) tft.println(WiFi.SSID()); 147 | 148 | // print your WiFi shield's IP address: 149 | IPAddress ip = WiFi.localIP(); 150 | Serial.print("IP Address: "); 151 | if (mode == SCREEN || mode == BOTH) tft.print("IP Address: "); 152 | Serial.println(ip); 153 | if (mode == SCREEN || mode == BOTH) tft.println(ip); 154 | 155 | // print the received signal strength: 156 | long rssi = WiFi.RSSI(); 157 | Serial.print("signal strength (RSSI):"); 158 | if (mode == SCREEN || mode == BOTH) tft.print("signal strength (RSSI):"); 159 | Serial.print(rssi); 160 | if (mode == SCREEN || mode == BOTH) tft.print(rssi); 161 | Serial.println(" dBm"); 162 | if (mode == SCREEN || mode == BOTH) tft.println(" dBm"); 163 | } 164 | 165 | void print2digits(int number, int mode) { 166 | if (number < 10) { 167 | if (mode == SERIAL || mode == BOTH) { 168 | Serial.print("0"); 169 | } 170 | if (mode == SCREEN || mode == BOTH) { 171 | tft.print("0"); 172 | } 173 | } 174 | if (mode == SERIAL || mode == BOTH) { 175 | Serial.print(number); 176 | } 177 | if (mode == SCREEN || mode == BOTH) { 178 | tft.print(number); 179 | } 180 | } 181 | 182 | unsigned long timeToDisplay(int mode) { 183 | unsigned long start = micros(); 184 | //tft.fillRect(0, 24, 6 * 8 * 2, 7 * 2, ILI9341_BLACK); 185 | tft.setCursor(0, 0); 186 | tft.setTextColor(ILI9341_WHITE); tft.setTextSize(3); 187 | printDate(mode); 188 | tft.setCursor(0, 24); 189 | tft.setTextColor(ILI9341_BLACK); tft.setTextSize(2); 190 | deleteTime(mode, false, howDifferentTime()); 191 | tft.setCursor(0, 24); 192 | tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2); 193 | printTime(mode); 194 | } 195 | 196 | void getCurrentTime() { 197 | currTime[0] = rtc.getHours(); 198 | currTime[1] = rtc.getMinutes(); 199 | currTime[2] = rtc.getSeconds(); 200 | } 201 | 202 | void copyTime() { 203 | prevTime[0] = currTime[0]; 204 | prevTime[1] = currTime[1]; 205 | prevTime[2] = currTime[2]; 206 | } 207 | 208 | boolean isDifferentTime() { 209 | boolean itIs = false; 210 | for (int i = 0; i < 3; i++) 211 | if (prevTime[i] != currTime[i]) 212 | itIs = true; 213 | return itIs; 214 | } 215 | 216 | int howDifferentTime() { 217 | int is = -1; 218 | // go backwards, biggest time is most significant 219 | for (int i = 2; i >= 0; i--) 220 | if (prevTime[i] != currTime[i]) 221 | is = i; 222 | return is; 223 | } 224 | 225 | // this method makes a HTTP connection to the server: 226 | void httpRequest(int mode) { 227 | // close any connection before send a new request. 228 | // This will free the socket on the Nina module 229 | client.stop(); 230 | 231 | // if there's a successful connection: 232 | if (client.connect(server, 80)) { 233 | Serial.println("connecting..."); 234 | // send the HTTP PUT request: 235 | client.println("GET /arduinoSpace/test.html HTTP/1.1"); 236 | client.println("Host: cuartielles.com"); 237 | client.println("User-Agent: ArduinoWiFi/1.1"); 238 | client.println("Connection: close"); 239 | client.println(); 240 | 241 | // note the time that the connection was made: 242 | lastConnectionTime = millis(); 243 | } else { 244 | // if you couldn't make a connection: 245 | if (mode == SCREEN || mode == BOTH) 246 | tft.println("connection failed"); 247 | if (mode == SERIAL || mode == BOTH) 248 | Serial.println("connection failed"); 249 | } 250 | } 251 | 252 | -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC_screen/s03e01_fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/WiFi_RTC_screen/s03e01_fritzing.png -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/img/s03e01_fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/img/s03e01_fritzing.png -------------------------------------------------------------------------------- /Season 3/Episode 1 - MKR1010 + TFT = Clock (Space Calendar I)/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 1 / Season 3 - MKR1010 + TFT = Clock 2 | This time we demo how to make a simple clock showing time, date, and the content from a website all at once. These TFT screens are not super speedy, therefore we made a system that cleans up just the area of the image that is going to be refreshed with new numbers. 3 | 4 | In this episode we present three programs showing the process to include a way to get the time from the internet (an NTP server), keep the time ticking inside the MKR1010 thanks to the RTCzero library, displaying the time on a TFT screen, and downloading the content from a website as a first step to later build a calendar that will be getting events from the net. 5 | 6 | You can watch this project being done by David Cuartielles, the co-founder of Arduino, by clicking into this link: https://youtu.be/bp7cSDMLxDk 7 | 8 | 9 | 10 | ## Ingredients 11 | - Arduino MKR1010 board 12 | - 2x buttons (not used in this episode, yet) 13 | - 1x TFT screen 14 | - Jumper wires 15 | 16 | 17 | ## Wiring 18 | ##### Connect the wires and components according to the fritzing below. 19 | ![alt text](https://github.com/arduino/livecast/raw/master/Season%203/Episode%201%20-%20MKR1010%20+%20TFT%20=%20Clock%20(Space%20Calendar%20I)/img/s03e01_fritzing.png "Fritzing image of the design") 20 | 21 | ## Code 22 | 23 | This week we present three programs: 24 | 25 | * WiFi_RTC: this program will get the time from an NTP server and use it as a reference to count the time using the RTCzero library 26 | 27 | * WiFi_RTC_revised: it does the same as the previous program, but in a slightly cleaner way, preparing the way to add the other functions to the calendar 28 | 29 | * WiFi_RTC_screen: uses a couple of constants named BOTH / SERIAL / SCREEN to determine whether the data will sent through the serial port, or be shown on the TFT screen ... or both! 30 | 31 | ## Outcome 32 | 33 | This project is just the first step towards building a calendar that will count time left until the next relevant event. Build it and let us know how it went on the official Arduino Discord channel or on the Arduino Forum. 34 | 35 | ## Next steps 36 | 37 | We will be adding a JSON decoder to extract the relevant information from an online calendar made in PHP, and maybe even download an image from a server and display it on the screen together with the rest of the information. 38 | -------------------------------------------------------------------------------- /Season 3/Episode 3 - Anemometer with Arduino Uno/S03E03_Fritzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 3/Episode 3 - Anemometer with Arduino Uno/S03E03_Fritzing.png -------------------------------------------------------------------------------- /Season 3/Episode 3 - Anemometer with Arduino Uno/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 3 - Anemometer with Arduino 2 | This example will show how to use an anemometer to measure windspeed using an Arduino UNO. 3 | 4 | 5 | ## Ingredients 6 | - Arduino UNO 7 | - Breadboard 8 | - 1x Anemometer 9 | - 1x Potentiometer 10 | - 1x LCD display 11 | - 9V battery 12 | - Jumper wires 13 | 14 | 15 | 16 | ## Wiring 17 | *Connect the wires and components according to the fritzing below.* 18 | ![alt text](https://github.com/arduino/livecast/raw/master/Season%203/Episode%203%20-%20Anemometer%20with%20Arduino%20Uno/S03E03_Fritzing.png "Logo Title Text 1") 19 | 20 | 21 | 22 | ## Code 23 | 24 | ```sh 25 | /* 26 | Wind speed + LCD example 27 | 28 | Using an anemometer to measure wind speed in m/s. 29 | The wind speed is then displayed on a LCD 30 | 31 | (c) 2019 Karl, Josefine & David for Arduino 32 | 33 | based on code by Joe Burg (c) 2014 34 | 35 | */ 36 | 37 | #include 38 | 39 | LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 40 | 41 | double x = 0; 42 | double y = 0; 43 | double a = 0; 44 | double b = 0; 45 | 46 | int windSensor = A1; 47 | float voltageMax = 2.0; 48 | float voltageMin = .4; 49 | float voltageConversionConstant = .004882814; 50 | float sensorVoltage = 0; 51 | 52 | float windSpeedMin = 0; 53 | float windSpeedMax = 32; 54 | 55 | int windSpeed = 0; 56 | int prevWindSpeed = 0; 57 | 58 | void setup() { 59 | // put your setup code here, to run once: 60 | lcd.begin(16, 2); 61 | Serial.begin(9600); 62 | } 63 | 64 | void loop() { 65 | // put your main code here, to run repeatedly: 66 | int sensorValue = analogRead(windSensor); 67 | 68 | float voltage = sensorValue * (5.0 / 1023.0); 69 | 70 | sensorVoltage = sensorValue * voltageConversionConstant; 71 | 72 | 73 | 74 | if (sensorVoltage <= voltageMin) { 75 | windSpeed = 0; //Check if voltage is below minimum value. If so, set wind speed to zero. 76 | } else { 77 | windSpeed = ((sensorVoltage - voltageMin) * windSpeedMax / (voltageMax - voltageMin)) * 2.232694; //For voltages above minimum value, use the linear relationship to calculate wind speed. 78 | } 79 | 80 | x = windSpeed; 81 | if (x >= y) { 82 | y = x; 83 | } else { 84 | y = y; 85 | } 86 | 87 | //Max voltage calculation 88 | 89 | a = sensorVoltage; 90 | if (a >= b) { 91 | b = a; 92 | } else { 93 | b = b; 94 | } 95 | if (windSpeed != prevWindSpeed) { 96 | Serial.println(windSpeed); 97 | Serial.println(sensorVoltage); 98 | prevWindSpeed = windSpeed; 99 | } 100 | 101 | lcd.setCursor(0, 0); 102 | lcd.print("Wind Speed "); 103 | lcd.setCursor(12, 0); 104 | lcd.print(windSpeed); 105 | lcd.print(" "); 106 | lcd.setCursor(11, 2); 107 | lcd.print("m/s"); 108 | delay(100); 109 | } 110 | 111 | ``` 112 | 113 | ## Start using 114 | 115 | After wiring and uploading the code, we can now start using the Anemometer. If everything is wired accordingly, spinning it will start printing the current m/s on the LCD screen. You can now find a suitable spot for the anemometer outside (perhaps start with outside the window) and see what kind of winds are passing through. The anemometer itself is supposed to be air and water proofed, but make sure the Arduino and the circuit is in a dry location to not damage any components. 116 | 117 | 118 | ## Outcome 119 | 120 | This is a part of our weather station series, where we use different components to see the weather conditions locally. This example shows how the voltage output from the anemometer is transformed into something that we can make sense out of, such as m/s, km/h or mph. The data we collect can also be used over a longer period of time through various extensions, where you can monitor how the wind has been for the past week for e.g. 121 | 122 | 123 | -------------------------------------------------------------------------------- /Season 3/Episode 3 - Anemometer with Arduino Uno/windspeed/windspeed.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Wind speed + LCD example 3 | 4 | Using an anemometer to measure wind speed in m/s. 5 | The wind speed is then displayed on a LCD 6 | 7 | (c) 2019 Karl, Josefine & David for Arduino 8 | 9 | based on code by Joe Burg (c) 2014 10 | 11 | */ 12 | 13 | #include 14 | 15 | LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 16 | 17 | double x = 0; 18 | double y = 0; 19 | double a = 0; 20 | double b = 0; 21 | 22 | int windSensor = A1; 23 | float voltageMax = 2.0; 24 | float voltageMin = .4; 25 | float voltageConversionConstant = .004882814; 26 | float sensorVoltage = 0; 27 | 28 | float windSpeedMin = 0; 29 | float windSpeedMax = 32; 30 | 31 | int windSpeed = 0; 32 | int prevWindSpeed = 0; 33 | 34 | void setup() { 35 | // put your setup code here, to run once: 36 | lcd.begin(16, 2); 37 | Serial.begin(9600); 38 | } 39 | 40 | void loop() { 41 | // put your main code here, to run repeatedly: 42 | int sensorValue = analogRead(windSensor); 43 | 44 | float voltage = sensorValue * (5.0 / 1023.0); 45 | 46 | sensorVoltage = sensorValue * voltageConversionConstant; 47 | 48 | 49 | 50 | if (sensorVoltage <= voltageMin) { 51 | windSpeed = 0; //Check if voltage is below minimum value. If so, set wind speed to zero. 52 | } else { 53 | windSpeed = ((sensorVoltage - voltageMin) * windSpeedMax / (voltageMax - voltageMin)) * 2.232694; //For voltages above minimum value, use the linear relationship to calculate wind speed. 54 | } 55 | 56 | x = windSpeed; 57 | if (x >= y) { 58 | y = x; 59 | } else { 60 | y = y; 61 | } 62 | 63 | //Max voltage calculation 64 | 65 | a = sensorVoltage; 66 | if (a >= b) { 67 | b = a; 68 | } else { 69 | b = b; 70 | } 71 | if (windSpeed != prevWindSpeed) { 72 | Serial.println(windSpeed); 73 | Serial.println(sensorVoltage); 74 | prevWindSpeed = windSpeed; 75 | } 76 | 77 | lcd.setCursor(0, 0); 78 | lcd.print("Wind Speed "); 79 | lcd.setCursor(12, 0); 80 | lcd.print(windSpeed); 81 | lcd.print(" "); 82 | lcd.setCursor(11, 2); 83 | lcd.print("m/s"); 84 | delay(100); 85 | } 86 | -------------------------------------------------------------------------------- /Season 3/Episode 6 - Rain Sensor/fritzing_e4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/Season 3/Episode 6 - Rain Sensor/fritzing_e4.png -------------------------------------------------------------------------------- /Season 3/Episode 6 - Rain Sensor/rainsensor/rainsensor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic weather condition example, using a DHT11 humidity/temperature 3 | sensor and a rain sensor. To see the data we are using the serial 4 | monitor for an easy setup. 5 | 6 | (c) 2019 Karl, Josefine & David for Arduino 7 | 8 | based on code by Circuit Basics (c) 2015 9 | 10 | */ 11 | 12 | //include the DHT library 13 | #include 14 | dht DHT; 15 | 16 | #define DHT11_PIN 7 17 | 18 | // lowest and highest sensor readings: 19 | const int minValue = 0; // sensor minimum 20 | const int maxValue = 1024; // sensor maximum 21 | 22 | void setup() { 23 | Serial.begin(9600); 24 | } 25 | void loop() { 26 | 27 | //read the rain sensor on A0 28 | int readSensor = analogRead(A0); 29 | 30 | //here we convert the analog value to a simple range of 0-2. 31 | int change = map(readSensor, minValue, maxValue, 0, 2); 32 | 33 | //here we check the DHT11 sensor for the current humidity and temperature 34 | int chk = DHT.read11(DHT11_PIN); 35 | 36 | //prints the values in the serial monitor and adding some text to describe the value 37 | Serial.print("Temperature = "); 38 | Serial.println(DHT.temperature); 39 | Serial.print("Humidity = "); 40 | Serial.println(DHT.humidity); 41 | 42 | //Below we use the values we get from the "change" int to print if it's raining or not 43 | //water on the sensor prints a 0 44 | if(change == 0) { 45 | Serial.println("it is raining"); 46 | } 47 | 48 | //no water on the sensor prints a 1 49 | if(change == 1) { 50 | Serial.println("no rain"); 51 | } 52 | 53 | delay(5000); // delay between reads 54 | } 55 | -------------------------------------------------------------------------------- /Season 3/Episode 6 - Rain Sensor/readme.md: -------------------------------------------------------------------------------- 1 | # Episode 3 - Rain Sensor + DHT11 with Arduino 2 | This example will show how to use a rain sensor and a DHT11 humidity & temperature sensor with an Arduino UNO. 3 | 4 | You can watch this project being done by David Cuartielles, the co-founder of Arduino on YouTube. 5 | 6 | [![Weather Station Project with D. Cuartielles](https://img.youtube.com/vi/phW2BzEDfKY/0.jpg)](https://www.youtube.com/watch?v=phW2BzEDfKY) 7 | 8 | ## Ingredients 9 | - Arduino Uno 10 | - Breadboard 11 | - Jumper Wires 12 | - DHT11 Sensor 13 | - Rain Sensor 14 | - Water Source (wet towel for e.g.) 15 | 16 | 17 | 18 | ## Wiring 19 | *Connect the wires and components according to the fritzing below.* 20 | ![alt text](https://github.com/arduino/livecast/raw/master/Season%203/Episode%206%20-%20Rain%20Sensor/fritzing_e4.png "Logo Title Text 1") 21 | 22 | 23 | 24 | ## Code 25 | 26 | ```sh 27 | /* 28 | Basic weather condition example, using a DHT11 humidity/temperature 29 | sensor and a rain sensor. To see the data we are using the serial 30 | monitor for an easy setup. 31 | 32 | (c) 2019 Karl, Josefine & David for Arduino 33 | 34 | based on code by Circuit Basics (c) 2015 35 | 36 | */ 37 | 38 | //include the DHT library 39 | #include 40 | dht DHT; 41 | 42 | #define DHT11_PIN 7 43 | 44 | // lowest and highest sensor readings: 45 | const int minValue = 0; // sensor minimum 46 | const int maxValue = 1024; // sensor maximum 47 | 48 | void setup() { 49 | Serial.begin(9600); 50 | } 51 | void loop() { 52 | 53 | //read the rain sensor on A0 54 | int readSensor = analogRead(A0); 55 | 56 | //here we convert the analog value to a simple range of 0-2. 57 | int change = map(readSensor, minValue, maxValue, 0, 2); 58 | 59 | //here we check the DHT11 sensor for the current humidity and temperature 60 | int chk = DHT.read11(DHT11_PIN); 61 | 62 | //prints the values in the serial monitor and adding some text to describe the value 63 | Serial.print("Temperature = "); 64 | Serial.println(DHT.temperature); 65 | Serial.print("Humidity = "); 66 | Serial.println(DHT.humidity); 67 | 68 | //Below we use the values we get from the "change" int to print if it's raining or not 69 | //water on the sensor prints a 0 70 | if(change == 0) { 71 | Serial.println("it is raining"); 72 | } 73 | 74 | //no water on the sensor prints a 1 75 | if(change == 1) { 76 | Serial.println("no rain"); 77 | } 78 | 79 | delay(5000); // delay between reads 80 | } 81 | 82 | ``` 83 | 84 | ## Start using 85 | 86 | After wiring and uploading the code, we can now start using this example. The DHT11 sensor will continuously measure the humidity and temperature of the environment it is in, while the rain sensor will measure whether the component is wet or not. In the code, we have converted the range of values (0-1023) of the sensor to a simple 0-2 range, just indicating if it is wet or not using a simple set of if statements. All three values (humidity, temperature & rain) will then be printed in the serial monitor every 5 seconds (as can be seen in the bottom of the code). 87 | 88 | 89 | ## Outcome 90 | 91 | This is a part of our weather station series, where we use different components to see the weather conditions locally. This example takes three important weather conditions, to get an overall view on how your local weather is. This project is best suitable for outdoors measurements, but it is good to try out indoors at first. This is a good example on how we measure both digital (DHT11 sensor) and analog (rain sensor), to collect data on your local environment. Instead of using the serial monitor as a visualization method, you can now think of other ways you want the data to be displayed, perhaps through a set of LEDs, an LCD screen or another actuator such as sound. 92 | 93 | -------------------------------------------------------------------------------- /img/livecast_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/livecast/63b3cb6c9b3a75b4176202816b09ea22ba0c7c60/img/livecast_1.png --------------------------------------------------------------------------------