WS2812B RGB LED Brightness Control & Color Mixing
Using 10K Potentiometers + 16x2 LCD w/ I2C backpack (optional)
Components and supplies
1
Arduino Nano R3
1
I2C 16x2 Arduino LCD Display Module
1
Breadboard (generic)
1
Jumper wires (generic)
1
LED Strip, NeoPixel Digital RGB
4
Rotary potentiometer (generic)
Apps and platforms
1
VS Code
1
Arduino IDE
1
PlatformIO IDE
Project description
Code
Color Mixing w/ LCD
arduino
1#include <FastLED.h> 2#include "LiquidCrystal_PCF8574.h" 3#define NUM_LEDS 1 4#define DATA_PIN 2 5#define LCD_ADDRESS 0x27 6#define LCD_ROWS 2 7#define LCD_COLUMNS 16 8#define SCROLL_DELAY 150 9#define BACKLIGHT 255 10LiquidCrystal_PCF8574 LCDi2C; 11 12CRGB leds[NUM_LEDS]; 13 14int BrightPot = A0; 15int BrightPotVal = 0; 16int BrightOutVal = 0; 17 18int RedPot = A1; 19int RedPotVal = 0; 20int RedOutVal = 0; 21 22int GreenPot = A2; 23int GreenPotVal = 0; 24int GreenOutVal = 0; 25 26int BluePot = A3; 27int BluePotVal = 0; 28int BlueOutVal = 0; 29 30void setup() 31{ 32 Serial.begin(9600); 33 LCDi2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT); 34 FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); 35} 36 37void loop() 38{ 39 40 //BRIGHTNESS 41 FastLED.setBrightness(BrightOutVal); 42 BrightPotVal = analogRead(BrightPot); 43 BrightOutVal = map(BrightPotVal, 0, 1023, 0, 255); 44 analogWrite(NUM_LEDS, BrightOutVal); 45 46 //RED 47 RedPotVal = analogRead(RedPot); 48 RedOutVal = map(RedPotVal, 0, 1023, 0, 255); 49 analogWrite(NUM_LEDS, RedOutVal); 50 51 //GREEN 52 GreenPotVal = analogRead(GreenPot); 53 GreenOutVal = map(GreenPotVal, 0, 1023, 0, 255); 54 analogWrite(NUM_LEDS, GreenOutVal); 55 56 //BLUE 57 BluePotVal = analogRead(BluePot); 58 BlueOutVal = map(BluePotVal, 0, 1023, 0, 255); 59 analogWrite(NUM_LEDS, BlueOutVal); 60 61 LCDi2C.setCursor(0, 0); 62 LCDi2C.print("Brightness:"); 63 LCDi2C.print(BrightOutVal); 64 LCDi2C.print(" "); 65 LCDi2C.setCursor(0, 1); 66 LCDi2C.print("R:"); 67 LCDi2C.print(RedOutVal); 68 LCDi2C.print(" G:"); 69 LCDi2C.print(GreenOutVal); 70 LCDi2C.print(" B:"); 71 LCDi2C.print(BlueOutVal); 72 LCDi2C.print(" "); 73 74 leds[0] = CRGB(RedOutVal, GreenOutVal, BlueOutVal); 75 76 FastLED.show(); 77}
Brightness Test
arduino
1#include <FastLED.h> 2#define NUM_LEDS 1 3#define DATA_PIN 2 4 5CRGB leds[NUM_LEDS]; 6 7int Pot = A0; 8int PotVal = 0; 9int OutVal = 0; 10 11 12void setup() { 13 Serial.begin(9600); 14 FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); 15 16} 17 18void loop() { 19 PotVal = analogRead(Pot); 20 Serial.println(OutVal); 21 OutVal = map(PotVal, 0, 1023, 0, 255); 22 23 analogWrite(NUM_LEDS, OutVal); 24 25 26 FastLED.setBrightness(OutVal); 27 28 leds[0] = CRGB(255, 255, 255); 29 FastLED.show(); 30}
Potentiometer Testing Code
arduino
1int Pot = A0; 2int PotVal = 0; 3 4void setup() { 5 Serial.begin(9600); 6 7} 8 9void loop() { 10 PotVal = analogRead(Pot); 11 Serial.println(PotVal); 12}
FastLED Library
Brightness Test
arduino
1#include <FastLED.h> 2#define NUM_LEDS 1 3#define DATA_PIN 2 4 5CRGB leds[NUM_LEDS]; 6 7int Pot = A0; 8int PotVal = 0; 9int OutVal = 0; 10 11 12void setup() { 13 Serial.begin(9600); 14 FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); 15 16} 17 18void loop() { 19 PotVal = analogRead(Pot); 20 Serial.println(OutVal); 21 OutVal = map(PotVal, 0, 1023, 0, 255); 22 23 analogWrite(NUM_LEDS, OutVal); 24 25 26 FastLED.setBrightness(OutVal); 27 28 leds[0] = CRGB(255, 255, 255); 29 FastLED.show(); 30}
LiquidCrystal_PCF8574.cpp
c_cpp
1/// 2/// \\file LiquidCrystal_PCF8574.cpp 3/// \\brief LiquidCrystal (LCD) library with PCF8574 I2C adapter. 4/// 5/// \\author Matthias Hertel, http://www.mathertel.de 6/// \\copyright Copyright (c) 2014 by Matthias Hertel.\ 7 8/// This work is licensed under a BSD style license.\ 9 10/// See http://www.mathertel.de/License.aspx 11/// 12/// \\details 13/// This is a library for driving LiquidCrystal displays (LCD) by using the I2C bus and an PCF8574 I2C adapter. 14/// This library is derived from the original Arduino LiquidCrystal library and uses the original Wire library for communication. 15/// 16/// More documentation and source code is available at http://www.mathertel.de/Arduino 17/// 18/// ChangeLog see: LiquidCrystal_PCF8574.h 19 20#include "LiquidCrystal_PCF8574.h" 21 22#include <stdio.h> 23#include <string.h> 24#include <inttypes.h> 25#include "Arduino.h" 26#include <Wire.h> 27 28/// Definitions on how the PCF8574 is connected to the LCD 29 30/// These are Bit-Masks for the special signals and background light 31#define PCF_RS 0x01 32#define PCF_RW 0x02 33#define PCF_EN 0x04 34#define PCF_BACKLIGHT 0x08 35 36// Definitions on how the PCF8574 is connected to the LCD 37// These are Bit-Masks for the special signals and Background 38#define RSMODE_CMD 0 39#define RSMODE_DATA 1 40 41 42// When the display powers up, it is configured as follows: 43// 44// 1. Display clear 45// 2. Function set: 46// DL = 1; 8-bit interface data 47// N = 0; 1-line display 48// F = 0; 5x8 dot character font 49// 3. Display on/off control: 50// D = 0; Display off 51// C = 0; Cursor off 52// B = 0; Blinking off 53// 4. Entry mode set: 54// I/D = 1; Increment by 1 55// S = 0; No shift 56// 57// Note, however, that resetting the Arduino doesn't reset the LCD, so we 58// can't assume that its in that state when a sketch starts (and the 59// LiquidCrystal constructor is called). 60 61// modification: 62// don't use ports from Arduino, but use ports from Wire 63 64// a nibble is a half Byte 65 66// NEW: http://playground.arduino.cc//Code/LCDAPI 67// NEW: setBacklight 68 69LiquidCrystal_PCF8574::LiquidCrystal_PCF8574() 70{ 71 //_backlight = 255; 72} // LiquidCrystal_PCF8574 73 74LiquidCrystal_PCF8574::LiquidCrystal_PCF8574(uint8_t addr) 75{ 76 _Addr = addr; 77 _backlight = 0; 78} // LiquidCrystal_PCF8574 79 80void LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines, uint8_t addr, uint8_t backlight) 81{ 82 _backlight = backlight; 83 _Addr = addr; 84 begin(cols, lines); 85} 86 87void LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { 88 // cols ignored ! 89 _numlines = lines; 90 91 _displayfunction = 0; 92 93 if (lines > 1) { 94 _displayfunction |= LCD_2LINE; 95 } 96 97 // for some 1 line displays you can select a 10 pixel high font 98 if ((dotsize != 0) && (lines == 1)) { 99 _displayfunction |= LCD_5x10DOTS; 100 } 101 102 // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 103 // according to datasheet, we need at least 40ms after power rises above 2.7V 104 // before sending commands. Arduino can turn on way befor 4.5V so we'll wait 50 105 Wire.begin(); 106 107 // initializing th display 108 _write2Wire(0x00, LOW, false); 109 delayMicroseconds(50000); 110 111 // put the LCD into 4 bit mode according to the hitachi HD44780 datasheet figure 26, pg 47 112 _sendNibble(0x03, RSMODE_CMD); 113 delayMicroseconds(4500); 114 _sendNibble(0x03, RSMODE_CMD); 115 delayMicroseconds(4500); 116 _sendNibble(0x03, RSMODE_CMD); 117 delayMicroseconds(150); 118 // finally, set to 4-bit interface 119 _sendNibble(0x02, RSMODE_CMD); 120 121 // finally, set # lines, font size, etc. 122 _command(LCD_FUNCTIONSET | _displayfunction); 123 124 // turn the display on with no cursor or blinking default 125 _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 126 display(); 127 128 // clear it off 129 clear(); 130 131 // Initialize to default text direction (for romance languages) 132 _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 133 // set the entry mode 134 _command(LCD_ENTRYMODESET | _displaymode); 135 136 setBacklight(_backlight); 137 checkI2CConnection(); 138} 139 140/********** high level commands, for the user! */ 141void LiquidCrystal_PCF8574::clear() 142{ 143 _command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 144 delayMicroseconds(2000); // this command takes a long time! 145} 146 147void LiquidCrystal_PCF8574::home() 148{ 149 _command(LCD_RETURNHOME); // set cursor position to zero 150 delayMicroseconds(2000); // this command takes a long time! 151} 152 153 154/// Set the cursor to a new position. 155void LiquidCrystal_PCF8574::setCursor(uint8_t col, uint8_t row) 156{ 157 int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 158 if ( row >= _numlines ) { 159 row = _numlines-1; // we count rows starting w/0 160 } 161 162 _command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 163} 164 165/** select begining of line 166 * line - 1 for first row, 2 for second row 167 * 168 */ 169void LiquidCrystal_PCF8574::selectLine(uint8_t line) 170{ 171 setCursor(0, line - 1); 172} 173 174// Turn the display on/off (quickly) 175void LiquidCrystal_PCF8574::noDisplay() { 176 _displaycontrol &= ~LCD_DISPLAYON; 177 _command(LCD_DISPLAYCONTROL | _displaycontrol); 178} 179void LiquidCrystal_PCF8574::display() { 180 _displaycontrol |= LCD_DISPLAYON; 181 _command(LCD_DISPLAYCONTROL | _displaycontrol); 182} 183 184// Turns the underline cursor on/off 185void LiquidCrystal_PCF8574::noCursor() { 186 _displaycontrol &= ~LCD_CURSORON; 187 _command(LCD_DISPLAYCONTROL | _displaycontrol); 188} 189void LiquidCrystal_PCF8574::cursor() { 190 _displaycontrol |= LCD_CURSORON; 191 _command(LCD_DISPLAYCONTROL | _displaycontrol); 192} 193 194// Turn on and off the blinking cursor 195void LiquidCrystal_PCF8574::noBlink() { 196 _displaycontrol &= ~LCD_BLINKON; 197 _command(LCD_DISPLAYCONTROL | _displaycontrol); 198} 199void LiquidCrystal_PCF8574::blink() { 200 _displaycontrol |= LCD_BLINKON; 201 _command(LCD_DISPLAYCONTROL | _displaycontrol); 202} 203 204/** These commands scroll the display without changing the RAM 205 * charsToScroll - how many chars to scroll left 206 * scrollSpeed - define scrolling speed, im milliseconds. 207 */ 208 209void LiquidCrystal_PCF8574::scrollDisplayLeft(int charsToScroll, int scrollSpeed) { 210 for (int i=0 ; i < charsToScroll ; i++) 211 { 212 _command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 213 delay(scrollSpeed); 214 } 215} 216 217/** These commands scroll the display without changing the RAM 218 * charsToScroll - how many chars to scroll right 219 * scrollSpeed - define scrolling speed, im milliseconds. 220 */ 221 222void LiquidCrystal_PCF8574::scrollDisplayRight(int charsToScroll, int scrollSpeed) { 223 for (int i=0 ; i < charsToScroll ; i++) 224 { 225 _command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 226 delay(scrollSpeed); 227 } 228} 229 230// This is for text that flows Left to Right 231void LiquidCrystal_PCF8574::leftToRight(void) { 232 _displaymode |= LCD_ENTRYLEFT; 233 _command(LCD_ENTRYMODESET | _displaymode); 234} 235 236// This is for text that flows Right to Left 237void LiquidCrystal_PCF8574::rightToLeft(void) { 238 _displaymode &= ~LCD_ENTRYLEFT; 239 _command(LCD_ENTRYMODESET | _displaymode); 240} 241 242// This will 'right justify' text from the cursor 243void LiquidCrystal_PCF8574::autoscroll(void) { 244 _displaymode |= LCD_ENTRYSHIFTINCREMENT; 245 _command(LCD_ENTRYMODESET | _displaymode); 246} 247 248// This will 'left justify' text from the cursor 249void LiquidCrystal_PCF8574::noAutoscroll(void) { 250 _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 251 _command(LCD_ENTRYMODESET | _displaymode); 252} 253 254 255/// Setting the brightness of the background display light. 256/// The backlight can be switched on and off. 257/// The current brightness is stored in the private _backlight variable to have it available for further data transfers. 258void LiquidCrystal_PCF8574::setBacklight(uint8_t brightness) { 259 _backlight = brightness; 260 // send no data but set the background-pin right; 261 _write2Wire(0x00, RSMODE_DATA, false); 262} // setBacklight 263 264 265// Allows us to fill the first 8 CGRAM locations 266// with custom characters 267void LiquidCrystal_PCF8574::createChar(uint8_t location, uint8_t charmap[]) { 268 location &= 0x7; // we only have 8 locations 0-7 269 _command(LCD_SETCGRAMADDR | (location << 3)); 270 for (int i=0; i<8; i++) { 271 write(charmap[i]); 272 } 273} 274 275/* The write function is needed for derivation from the Print class. */ 276inline size_t LiquidCrystal_PCF8574::write(uint8_t value) { 277 _send(value, RSMODE_DATA); 278 return 1; // assume sucess 279} 280 281/* ----- low level functions ----- */ 282 283inline void LiquidCrystal_PCF8574::_command(uint8_t value) { 284 _send(value, RSMODE_CMD); 285} // _command() 286 287 288// write either command or data 289void LiquidCrystal_PCF8574::_send(uint8_t value, uint8_t mode) { 290 // separate the 4 value-nibbles 291 uint8_t valueLo = value & 0x0F; 292 uint8_t valueHi = value>>4 & 0x0F; 293 294 _sendNibble(valueHi, mode); 295 _sendNibble(valueLo, mode); 296} // _send() 297 298 299// write a nibble / halfByte with handshake 300void LiquidCrystal_PCF8574::_sendNibble(uint8_t halfByte, uint8_t mode) { 301 _write2Wire(halfByte, mode, true); 302 delayMicroseconds(1); // enable pulse must be >450ns 303 _write2Wire(halfByte, mode, false); 304 delayMicroseconds(37); // commands need > 37us to settle 305} // _sendNibble 306 307 308// private function to change the PCF8674 pins to the given value 309void LiquidCrystal_PCF8574::_write2Wire(uint8_t halfByte, uint8_t mode, uint8_t enable) { 310 // map the given values to the hardware of the I2C schema 311 uint8_t i2cData = halfByte << 4; 312 if (mode > 0) i2cData |= PCF_RS; 313 // PCF_RW is never used. 314 if (enable > 0) i2cData |= PCF_EN; 315 if (_backlight > 0) i2cData |= PCF_BACKLIGHT; 316 317 Wire.beginTransmission(_Addr); 318 Wire.write(i2cData); 319 Wire.endTransmission(); 320} // write2Wire 321 322bool LiquidCrystal_PCF8574::checkI2CConnection() 323{ 324 int error; 325 // See http://playground.arduino.cc/Main/I2cScanner 326 Wire.begin(); 327 Wire.beginTransmission(_Addr); 328 error = Wire.endTransmission(); 329 330 if (error) 331 { 332 Serial.println("LCD not found."); 333 } 334 return error; 335 336} 337 338// The End. 339
Color Mixing
arduino
1#include <FastLED.h> 2#define NUM_LEDS 1 3#define DATA_PIN 2 4 5CRGB leds[NUM_LEDS]; 6 7int BrightPot = A0; 8int BrightPotVal = 0; 9int BrightOutVal = 0; 10 11int RedPot = A1; 12int RedPotVal = 0; 13int RedOutVal = 0; 14 15int GreenPot = A2; 16int GreenPotVal = 0; 17int GreenOutVal = 0; 18 19int BluePot = A3; 20int BluePotVal = 0; 21int BlueOutVal = 0; 22 23void setup() { 24 Serial.begin(9600); 25 FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); 26 27} 28 29void loop() { 30 31 32//BRIGHTNESS 33 FastLED.setBrightness(BrightOutVal); 34 BrightPotVal = analogRead(BrightPot); 35 BrightOutVal = map(BrightPotVal, 0, 1023, 0, 255); 36 analogWrite(NUM_LEDS, BrightOutVal); 37 38 if (BrightOutVal <= 5) 39 { 40 Serial.print(""); 41 } 42 if (BrightOutVal >= 10) 43 { 44 Serial.print("Brightness Value= "); 45 Serial.println(BrightOutVal); 46 } 47 48 49 //RED 50 RedPotVal = analogRead(RedPot); 51 RedOutVal = map(RedPotVal, 0, 1023, 0, 255); 52 analogWrite(NUM_LEDS, RedOutVal); 53 54 if (RedOutVal <= 5) 55 { 56 Serial.print(""); 57 } 58 if (RedOutVal >= 10) 59 { 60 Serial.print("Red Value= "); 61 Serial.println(RedOutVal); 62 } 63 64 65 //GREEN 66 GreenPotVal = analogRead(GreenPot); 67 GreenOutVal = map(GreenPotVal, 0, 1023, 0, 255); 68 analogWrite(NUM_LEDS, GreenOutVal); 69 70 if (GreenOutVal <= 5) 71 { 72 Serial.print(""); 73 } 74 if (GreenOutVal >= 10) 75 { 76 Serial.print("Green Value= "); 77 Serial.println(GreenOutVal); 78 } 79 80 81 //BLUE 82 BluePotVal = analogRead(BluePot); 83 BlueOutVal = map(BluePotVal, 0, 1023, 0, 255); 84 analogWrite(NUM_LEDS, BlueOutVal); 85 86 if (BlueOutVal <= 5) 87 { 88 Serial.print(""); 89 } 90 if (BlueOutVal >= 10) 91 { 92 Serial.print("Blue Value= "); 93 Serial.println(BlueOutVal); 94 } 95 96 leds[0] = CRGB(RedOutVal, GreenOutVal, BlueOutVal); 97 98 FastLED.show(); 99}
LiquidCrystal Library
Potentiometer Testing Code
arduino
1int Pot = A0; 2int PotVal = 0; 3 4void setup() { 5 Serial.begin(9600); 6 7} 8 9void 10 loop() { 11 PotVal = analogRead(Pot); 12 Serial.println(PotVal); 13}
FastLED Library
LiquidCrystal_PCF8574.h
c_cpp
1/// 2/// \\file LiquidCrystal_PCF8574.h 3/// \\brief LiquidCrystal library with PCF8574 I2C adapter. 4/// 5/// \\author Matthias Hertel, http://www.mathertel.de 6/// \\copyright Copyright (c) 2014 by Matthias Hertel.\ 7 8/// This work is licensed under a BSD style license.\ 9 10/// See http://www.mathertel.de/License.aspx 11/// 12/// Copyright (c) 2005-2012 by Matthias Hertel, http://www.mathertel.de/ 13/// All rights reserved. 14/// 15/// * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 16/// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 17/// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the 18/// documentation and/or other materials provided with the distribution. Neither the name of the copyright owners nor the names of its 19/// contributors may be used to endorse or promote products derived from this software without specific prior written permission. 20/// 21/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 22/// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23/// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24/// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25/// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26/// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 29/// \\details 30/// This is a library for driving LiquidCrystal displays (LCD) by using the I2C bus and an PCF8574 I2C adapter. 31/// This library is derived from the original Arduino LiquidCrystal library and uses the original Wire library for communication. 32/// 33/// ChangeLog: 34/// -------- 35/// * 19.10.2013 created. 36/// * 24.05.2015 Arduino Library Manager compatible. 37/// * 20.12.2016 circuito.io: 38/// * Added scrolling multiple chars to scrolling functions 39/// * Added selectLine function, same as setCursor(0, line - 1) 40/// * Added checkI2CConnection - prints to the serial monitor if connection faild. it is called inside begin. 41 42 43 44#ifndef LiquidCrystal_PCF8574_h 45#define LiquidCrystal_PCF8574_h 46 47#include <inttypes.h> 48#include "Print.h" 49 50// commands 51#define LCD_CLEARDISPLAY 0x01 52#define LCD_RETURNHOME 0x02 53#define LCD_ENTRYMODESET 0x04 54#define LCD_DISPLAYCONTROL 0x08 55#define LCD_CURSORSHIFT 0x10 56#define LCD_FUNCTIONSET 0x20 57#define LCD_SETCGRAMADDR 0x40 58#define LCD_SETDDRAMADDR 0x80 59 60// flags for display entry mode 61#define LCD_ENTRYRIGHT 0x00 62#define LCD_ENTRYLEFT 0x02 63#define LCD_ENTRYSHIFTINCREMENT 0x01 64#define LCD_ENTRYSHIFTDECREMENT 0x00 65 66// flags for display on/off control 67#define LCD_DISPLAYON 0x04 68#define LCD_DISPLAYOFF 0x00 69#define LCD_CURSORON 0x02 70#define LCD_CURSOROFF 0x00 71#define LCD_BLINKON 0x01 72#define LCD_BLINKOFF 0x00 73 74// flags for display/cursor shift 75#define LCD_DISPLAYMOVE 0x08 76#define LCD_CURSORMOVE 0x00 77#define LCD_MOVERIGHT 0x04 78#define LCD_MOVELEFT 0x00 79 80// flags for function set 81#define LCD_8BITMODE 0x10 82#define LCD_4BITMODE 0x00 83#define LCD_2LINE 0x08 84#define LCD_1LINE 0x00 85#define LCD_5x10DOTS 0x04 86#define LCD_5x8DOTS 0x00 87 88class LiquidCrystal_PCF8574 : public Print { 89public: 90 91 LiquidCrystal_PCF8574(); 92 LiquidCrystal_PCF8574(uint8_t addr); 93 94 void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); 95 void begin(uint8_t cols, uint8_t lines, uint8_t addr, uint8_t backlight); 96 bool checkI2CConnection(); 97 98 void clear(); 99 void home(); 100 101 void noDisplay(); 102 void display(); 103 void noBlink(); 104 void blink(); 105 void noCursor(); 106 void cursor(); 107 void scrollDisplayLeft(int charsToScroll, int scrollSpeed); 108 void scrollDisplayRight(int charsToScroll, int scrollSpeed); 109 void leftToRight(); 110 void rightToLeft(); 111 void autoscroll(); 112 void noAutoscroll(); 113 114 void setBacklight(uint8_t brightness); 115 116 void createChar(uint8_t, uint8_t[]); 117 void setCursor(uint8_t col, uint8_t row); 118 void selectLine(uint8_t line); 119 120 virtual size_t write(uint8_t); 121 using Print::write; 122 123private: 124 // low level functions 125 void _command(uint8_t); 126 void _send(uint8_t value, uint8_t mode); 127 void _sendNibble(uint8_t halfByte, uint8_t mode); 128 void _write2Wire(uint8_t halfByte, uint8_t mode, uint8_t enable); 129 130// NEW: 131 uint8_t _Addr; ///< Wire Address of the LCD 132 uint8_t _backlight; ///< the backlight intensity 133 134 uint8_t _displayfunction; ///< lines and dots mode 135 uint8_t _displaycontrol; ///< cursor, display, blink flags 136 uint8_t _displaymode; ///< left2right, autoscroll 137 138 uint8_t _numlines; ///< The number of rows the display supports. 139}; 140 141#endif 142
LiquidCrystal Library
Color Mixing w/ LCD
arduino
1#include <FastLED.h> 2#include "LiquidCrystal_PCF8574.h" 3#define 4 NUM_LEDS 1 5#define DATA_PIN 2 6#define LCD_ADDRESS 0x27 7#define LCD_ROWS 8 2 9#define LCD_COLUMNS 16 10#define SCROLL_DELAY 150 11#define BACKLIGHT 255 12LiquidCrystal_PCF8574 13 LCDi2C; 14 15CRGB leds[NUM_LEDS]; 16 17int BrightPot = A0; 18int BrightPotVal 19 = 0; 20int BrightOutVal = 0; 21 22int RedPot = A1; 23int RedPotVal = 0; 24int 25 RedOutVal = 0; 26 27int GreenPot = A2; 28int GreenPotVal = 0; 29int GreenOutVal 30 = 0; 31 32int BluePot = A3; 33int BluePotVal = 0; 34int BlueOutVal = 0; 35 36void 37 setup() 38{ 39 Serial.begin(9600); 40 LCDi2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, 41 BACKLIGHT); 42 FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); 43} 44 45void 46 loop() 47{ 48 49 //BRIGHTNESS 50 FastLED.setBrightness(BrightOutVal); 51 52 BrightPotVal = analogRead(BrightPot); 53 BrightOutVal = map(BrightPotVal, 0, 54 1023, 0, 255); 55 analogWrite(NUM_LEDS, BrightOutVal); 56 57 //RED 58 RedPotVal 59 = analogRead(RedPot); 60 RedOutVal = map(RedPotVal, 0, 1023, 0, 255); 61 analogWrite(NUM_LEDS, 62 RedOutVal); 63 64 //GREEN 65 GreenPotVal = analogRead(GreenPot); 66 GreenOutVal 67 = map(GreenPotVal, 0, 1023, 0, 255); 68 analogWrite(NUM_LEDS, GreenOutVal); 69 70 71 //BLUE 72 BluePotVal = analogRead(BluePot); 73 BlueOutVal = map(BluePotVal, 74 0, 1023, 0, 255); 75 analogWrite(NUM_LEDS, BlueOutVal); 76 77 LCDi2C.setCursor(0, 78 0); 79 LCDi2C.print("Brightness:"); 80 LCDi2C.print(BrightOutVal); 81 LCDi2C.print(" 82 "); 83 LCDi2C.setCursor(0, 1); 84 LCDi2C.print("R:"); 85 LCDi2C.print(RedOutVal); 86 87 LCDi2C.print(" G:"); 88 LCDi2C.print(GreenOutVal); 89 LCDi2C.print(" B:"); 90 91 LCDi2C.print(BlueOutVal); 92 LCDi2C.print(" "); 93 94 leds[0] 95 = CRGB(RedOutVal, GreenOutVal, BlueOutVal); 96 97 FastLED.show(); 98}
LiquidCrystal_PCF8574.cpp
c_cpp
1/// 2/// \\file LiquidCrystal_PCF8574.cpp 3/// \\brief LiquidCrystal 4 (LCD) library with PCF8574 I2C adapter. 5/// 6/// \\author Matthias Hertel, 7 http://www.mathertel.de 8/// \\copyright Copyright (c) 2014 by Matthias Hertel.\ 9 10/// 11 This work is licensed under a BSD style license.\ 12 13/// See http://www.mathertel.de/License.aspx 14/// 15 16/// \\details 17/// This is a library for driving LiquidCrystal displays (LCD) 18 by using the I2C bus and an PCF8574 I2C adapter. 19/// This library is derived 20 from the original Arduino LiquidCrystal library and uses the original Wire library 21 for communication. 22/// 23/// More documentation and source code is available 24 at http://www.mathertel.de/Arduino 25/// 26/// ChangeLog see: LiquidCrystal_PCF8574.h 27 28#include 29 "LiquidCrystal_PCF8574.h" 30 31#include <stdio.h> 32#include <string.h> 33#include 34 <inttypes.h> 35#include "Arduino.h" 36#include <Wire.h> 37 38/// Definitions 39 on how the PCF8574 is connected to the LCD 40 41/// These are Bit-Masks for the 42 special signals and background light 43#define PCF_RS 0x01 44#define PCF_RW 0x02 45#define 46 PCF_EN 0x04 47#define PCF_BACKLIGHT 0x08 48 49// Definitions on how the PCF8574 50 is connected to the LCD 51// These are Bit-Masks for the special signals and Background 52#define 53 RSMODE_CMD 0 54#define RSMODE_DATA 1 55 56 57// When the display powers up, 58 it is configured as follows: 59// 60// 1. Display clear 61// 2. Function set: 62 63// DL = 1; 8-bit interface data 64// N = 0; 1-line display 65// F 66 = 0; 5x8 dot character font 67// 3. Display on/off control: 68// D = 0; Display 69 off 70// C = 0; Cursor off 71// B = 0; Blinking off 72// 4. Entry mode 73 set: 74// I/D = 1; Increment by 1 75// S = 0; No shift 76// 77// Note, 78 however, that resetting the Arduino doesn't reset the LCD, so we 79// can't assume 80 that its in that state when a sketch starts (and the 81// LiquidCrystal constructor 82 is called). 83 84// modification: 85// don't use ports from Arduino, but use 86 ports from Wire 87 88// a nibble is a half Byte 89 90// NEW: http://playground.arduino.cc//Code/LCDAPI 91// 92 NEW: setBacklight 93 94LiquidCrystal_PCF8574::LiquidCrystal_PCF8574() 95{ 96 97 //_backlight = 255; 98} // LiquidCrystal_PCF8574 99 100LiquidCrystal_PCF8574::LiquidCrystal_PCF8574(uint8_t 101 addr) 102{ 103 _Addr = addr; 104 _backlight = 0; 105} // LiquidCrystal_PCF8574 106 107void 108 LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines, uint8_t addr, uint8_t 109 backlight) 110{ 111 _backlight = backlight; 112 _Addr = addr; 113 begin(cols, 114 lines); 115} 116 117void LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines, 118 uint8_t dotsize) { 119 // cols ignored ! 120 _numlines = lines; 121 122 _displayfunction 123 = 0; 124 125 if (lines > 1) { 126 _displayfunction |= LCD_2LINE; 127 } 128 129 130 // for some 1 line displays you can select a 10 pixel high font 131 if ((dotsize 132 != 0) && (lines == 1)) { 133 _displayfunction |= LCD_5x10DOTS; 134 } 135 136 137 // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 138 // according to datasheet, 139 we need at least 40ms after power rises above 2.7V 140 // before sending commands. 141 Arduino can turn on way befor 4.5V so we'll wait 50 142 Wire.begin(); 143 144 // 145 initializing th display 146 _write2Wire(0x00, LOW, false); 147 delayMicroseconds(50000); 148 149 150 // put the LCD into 4 bit mode according to the hitachi HD44780 datasheet 151 figure 26, pg 47 152 _sendNibble(0x03, RSMODE_CMD); 153 delayMicroseconds(4500); 154 155 _sendNibble(0x03, RSMODE_CMD); 156 delayMicroseconds(4500); 157 _sendNibble(0x03, 158 RSMODE_CMD); 159 delayMicroseconds(150); 160 // finally, set to 4-bit interface 161 162 _sendNibble(0x02, RSMODE_CMD); 163 164 // finally, set # lines, font size, etc. 165 166 _command(LCD_FUNCTIONSET | _displayfunction); 167 168 // turn the display on 169 with no cursor or blinking default 170 _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF 171 | LCD_BLINKOFF; 172 display(); 173 174 // clear it off 175 clear(); 176 177 178 // Initialize to default text direction (for romance languages) 179 _displaymode 180 = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 181 // set the entry mode 182 _command(LCD_ENTRYMODESET 183 | _displaymode); 184 185 setBacklight(_backlight); 186 checkI2CConnection(); 187} 188 189/********** 190 high level commands, for the user! */ 191void LiquidCrystal_PCF8574::clear() 192{ 193 194 _command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 195 196 delayMicroseconds(2000); // this command takes a long time! 197} 198 199void 200 LiquidCrystal_PCF8574::home() 201{ 202 _command(LCD_RETURNHOME); // set cursor 203 position to zero 204 delayMicroseconds(2000); // this command takes a long time! 205} 206 207 208/// 209 Set the cursor to a new position. 210void LiquidCrystal_PCF8574::setCursor(uint8_t 211 col, uint8_t row) 212{ 213 int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 214 215 if ( row >= _numlines ) { 216 row = _numlines-1; // we count rows starting 217 w/0 218 } 219 220 _command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 221} 222 223/** 224 select begining of line 225 * line - 1 for first row, 2 for second row 226 * 227 228 */ 229void LiquidCrystal_PCF8574::selectLine(uint8_t line) 230{ 231 setCursor(0, 232 line - 1); 233} 234 235// Turn the display on/off (quickly) 236void LiquidCrystal_PCF8574::noDisplay() 237 { 238 _displaycontrol &= ~LCD_DISPLAYON; 239 _command(LCD_DISPLAYCONTROL | _displaycontrol); 240} 241void 242 LiquidCrystal_PCF8574::display() { 243 _displaycontrol |= LCD_DISPLAYON; 244 _command(LCD_DISPLAYCONTROL 245 | _displaycontrol); 246} 247 248// Turns the underline cursor on/off 249void LiquidCrystal_PCF8574::noCursor() 250 { 251 _displaycontrol &= ~LCD_CURSORON; 252 _command(LCD_DISPLAYCONTROL | _displaycontrol); 253} 254void 255 LiquidCrystal_PCF8574::cursor() { 256 _displaycontrol |= LCD_CURSORON; 257 _command(LCD_DISPLAYCONTROL 258 | _displaycontrol); 259} 260 261// Turn on and off the blinking cursor 262void LiquidCrystal_PCF8574::noBlink() 263 { 264 _displaycontrol &= ~LCD_BLINKON; 265 _command(LCD_DISPLAYCONTROL | _displaycontrol); 266} 267void 268 LiquidCrystal_PCF8574::blink() { 269 _displaycontrol |= LCD_BLINKON; 270 _command(LCD_DISPLAYCONTROL 271 | _displaycontrol); 272} 273 274/** These commands scroll the display without changing 275 the RAM 276 * charsToScroll - how many chars to scroll left 277 * scrollSpeed 278 - define scrolling speed, im milliseconds. 279 */ 280 281void LiquidCrystal_PCF8574::scrollDisplayLeft(int 282 charsToScroll, int scrollSpeed) { 283 for (int i=0 ; i < charsToScroll ; i++) 284 285 { 286 _command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 287 delay(scrollSpeed); 288 289 } 290} 291 292/** These commands scroll the display without changing the RAM 293 294 * charsToScroll - how many chars to scroll right 295 * scrollSpeed - define scrolling 296 speed, im milliseconds. 297 */ 298 299void LiquidCrystal_PCF8574::scrollDisplayRight(int 300 charsToScroll, int scrollSpeed) { 301 for (int i=0 ; i < charsToScroll ; i++) 302 303 { 304 _command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 305 delay(scrollSpeed); 306 307 } 308} 309 310// This is for text that flows Left to Right 311void LiquidCrystal_PCF8574::leftToRight(void) 312 { 313 _displaymode |= LCD_ENTRYLEFT; 314 _command(LCD_ENTRYMODESET | _displaymode); 315} 316 317// 318 This is for text that flows Right to Left 319void LiquidCrystal_PCF8574::rightToLeft(void) 320 { 321 _displaymode &= ~LCD_ENTRYLEFT; 322 _command(LCD_ENTRYMODESET | _displaymode); 323} 324 325// 326 This will 'right justify' text from the cursor 327void LiquidCrystal_PCF8574::autoscroll(void) 328 { 329 _displaymode |= LCD_ENTRYSHIFTINCREMENT; 330 _command(LCD_ENTRYMODESET | 331 _displaymode); 332} 333 334// This will 'left justify' text from the cursor 335void 336 LiquidCrystal_PCF8574::noAutoscroll(void) { 337 _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 338 339 _command(LCD_ENTRYMODESET | _displaymode); 340} 341 342 343/// Setting the brightness 344 of the background display light. 345/// The backlight can be switched on and off. 346/// 347 The current brightness is stored in the private _backlight variable to have it available 348 for further data transfers. 349void LiquidCrystal_PCF8574::setBacklight(uint8_t 350 brightness) { 351 _backlight = brightness; 352 // send no data but set the background-pin 353 right; 354 _write2Wire(0x00, RSMODE_DATA, false); 355} // setBacklight 356 357 358// 359 Allows us to fill the first 8 CGRAM locations 360// with custom characters 361void 362 LiquidCrystal_PCF8574::createChar(uint8_t location, uint8_t charmap[]) { 363 location 364 &= 0x7; // we only have 8 locations 0-7 365 _command(LCD_SETCGRAMADDR | (location 366 << 3)); 367 for (int i=0; i<8; i++) { 368 write(charmap[i]); 369 } 370} 371 372/* 373 The write function is needed for derivation from the Print class. */ 374inline size_t 375 LiquidCrystal_PCF8574::write(uint8_t value) { 376 _send(value, RSMODE_DATA); 377 378 return 1; // assume sucess 379} 380 381/* ----- low level functions ----- */ 382 383inline 384 void LiquidCrystal_PCF8574::_command(uint8_t value) { 385 _send(value, RSMODE_CMD); 386} 387 // _command() 388 389 390// write either command or data 391void LiquidCrystal_PCF8574::_send(uint8_t 392 value, uint8_t mode) { 393 // separate the 4 value-nibbles 394 uint8_t valueLo 395 = value & 0x0F; 396 uint8_t valueHi = value>>4 & 0x0F; 397 398 _sendNibble(valueHi, 399 mode); 400 _sendNibble(valueLo, mode); 401} // _send() 402 403 404// write a nibble 405 / halfByte with handshake 406void LiquidCrystal_PCF8574::_sendNibble(uint8_t halfByte, 407 uint8_t mode) { 408 _write2Wire(halfByte, mode, true); 409 delayMicroseconds(1); 410 // enable pulse must be >450ns 411 _write2Wire(halfByte, mode, false); 412 413 delayMicroseconds(37); // commands need > 37us to settle 414} // _sendNibble 415 416 417// 418 private function to change the PCF8674 pins to the given value 419void LiquidCrystal_PCF8574::_write2Wire(uint8_t 420 halfByte, uint8_t mode, uint8_t enable) { 421 // map the given values to the hardware 422 of the I2C schema 423 uint8_t i2cData = halfByte << 4; 424 if (mode > 0) i2cData 425 |= PCF_RS; 426 // PCF_RW is never used. 427 if (enable > 0) i2cData |= PCF_EN; 428 429 if (_backlight > 0) i2cData |= PCF_BACKLIGHT; 430 431 Wire.beginTransmission(_Addr); 432 433 Wire.write(i2cData); 434 Wire.endTransmission(); 435} // write2Wire 436 437bool 438 LiquidCrystal_PCF8574::checkI2CConnection() 439{ 440 int error; 441 // See http://playground.arduino.cc/Main/I2cScanner 442 443 Wire.begin(); 444 Wire.beginTransmission(_Addr); 445 error = Wire.endTransmission(); 446 447 448 if (error) 449 { 450 Serial.println("LCD not found."); 451 } 452 453 return error; 454 455} 456 457// The End. 458
Color Mixing
arduino
1#include <FastLED.h> 2#define NUM_LEDS 1 3#define DATA_PIN 2 4 5CRGB 6 leds[NUM_LEDS]; 7 8int BrightPot = A0; 9int BrightPotVal = 0; 10int BrightOutVal 11 = 0; 12 13int RedPot = A1; 14int RedPotVal = 0; 15int RedOutVal = 0; 16 17int 18 GreenPot = A2; 19int GreenPotVal = 0; 20int GreenOutVal = 0; 21 22int BluePot 23 = A3; 24int BluePotVal = 0; 25int BlueOutVal = 0; 26 27void setup() { 28 Serial.begin(9600); 29 30 FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); 31 32} 33 34void 35 loop() { 36 37 38//BRIGHTNESS 39 FastLED.setBrightness(BrightOutVal); 40 BrightPotVal 41 = analogRead(BrightPot); 42 BrightOutVal = map(BrightPotVal, 0, 1023, 0, 255); 43 44 analogWrite(NUM_LEDS, BrightOutVal); 45 46 if (BrightOutVal <= 5) 47 { 48 49 Serial.print(""); 50 } 51 if (BrightOutVal >= 10) 52 { 53 Serial.print("Brightness 54 Value= "); 55 Serial.println(BrightOutVal); 56 } 57 58 59 //RED 60 61 RedPotVal = analogRead(RedPot); 62 RedOutVal = map(RedPotVal, 0, 1023, 0, 255); 63 64 analogWrite(NUM_LEDS, RedOutVal); 65 66 if (RedOutVal <= 5) 67 { 68 Serial.print(""); 69 70 } 71 if (RedOutVal >= 10) 72 { 73 Serial.print("Red Value= "); 74 Serial.println(RedOutVal); 75 76 } 77 78 79 //GREEN 80 GreenPotVal = analogRead(GreenPot); 81 GreenOutVal 82 = map(GreenPotVal, 0, 1023, 0, 255); 83 analogWrite(NUM_LEDS, GreenOutVal); 84 85 86 if (GreenOutVal <= 5) 87 { 88 Serial.print(""); 89 } 90 if (GreenOutVal 91 >= 10) 92 { 93 Serial.print("Green Value= "); 94 Serial.println(GreenOutVal); 95 96 } 97 98 99 //BLUE 100 BluePotVal = analogRead(BluePot); 101 BlueOutVal = 102 map(BluePotVal, 0, 1023, 0, 255); 103 analogWrite(NUM_LEDS, BlueOutVal); 104 105 106 if (BlueOutVal <= 5) 107 { 108 Serial.print(""); 109 } 110 if (BlueOutVal 111 >= 10) 112 { 113 Serial.print("Blue Value= "); 114 Serial.println(BlueOutVal); 115 116 } 117 118 leds[0] = CRGB(RedOutVal, GreenOutVal, BlueOutVal); 119 120 FastLED.show(); 121}
Downloadable files
Schematic Diagram
Schematic Diagram

Schematic Diagram
Schematic Diagram

Comments
Only logged in users can leave comments