The code compiles for me as well but similar to what I mentioned before, I cannot connect to the board while the display is attached to it after the compiled code is uploaded.
As I mentioned here:
Hi there,
So got it working here…I’m not using the SD card btw… wiring is a bit SKetch but hay it’s late.
Runs on Battery too!
A couple observations, I using an Xiao Nrf52840 Sense UPLOADING the Xiao must be in bootloader mode with drive present.
I’m using the Crystalfontz.com LIB Worked right away.
#include <epd4in2.h>
#include <epdif.h>
#include <epdpaint.h>
#include <fonts.h>
#include <imagedata.h>
//=============================================================================
// "Arduino" example program for Crystalfontz ePaper.
//
// This project is for the CFAP122250A2-0213 :
//
// https://www.crystalfontz.com/product/CFAP122250A2-0213
//
// It was written against a Seeduino v4.2 @3.3v. An Arduino UNO modified to
// operate at 3.3v should also work.
//-----------------------------------------------------------------------------
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org/>
//=============================================================================
// Connecting the Arduino to the display
//
// ARDUINO |Adapter |Wire Color |Function
// --------+--------+-----------+--------------------
// D3 |17 |Green |Busy Line
// D4 |18 |Brown |Reset Line
// D5 |15 |Purple |Data/Command Line
// D10 |16 |Blue |Chip Select Line
// D11 |14 |White |MOSI
// D13 |13 |Orange |Clock
// 3.3V |5 |Red |Power
// GND |3 |Black |Ground
//
// Short the following pins on the adapter board:
// BS2 -> GND
// RESE -> 2.2ohms
//=============================================================================
//Connecting the Arduino to the SD card
//A CFA10112 micro SD card adapter can be used: https://www.crystalfontz.com/product/cfa10112
//
// ARDUINO |Wire Color |Function
// ---------+-----------+--------------------
// D8 |Blue |CS
// D11 |Green |MOSI
// D12 |Purple |MISO
// D13 |Brown |CLK
//
//
//=============================================================================
// Creating image data arrays
//
// Bmp_to_epaper is code that will aid in creating bitmaps necessary from .bmp files.
// The code can be downloaded from the Crystalfontz website: https://www.Crystalfontz.com
// or it can be downloaded from github: https://github.com/crystalfontz/bmp_to_epaper
//=============================================================================
// The display is SPI, include the library header.
#include <SPI.h>
#include <SD.h>
//#include <avr/io.h>
// Include the images. These images were prepared with "bmp_to_epaper" which
// is available on the Crystalfontz site.
#include "Images_for_CFAP122250A20213.h"
#define ePaper_RST_0 (digitalWrite(EPD_RESET, LOW))
#define ePaper_RST_1 (digitalWrite(EPD_RESET, HIGH))
#define ePaper_CS_0 (digitalWrite(EPD_CS, LOW))
#define ePaper_CS_1 (digitalWrite(EPD_CS, HIGH))
#define ePaper_DC_0 (digitalWrite(EPD_DC, LOW))
#define ePaper_DC_1 (digitalWrite(EPD_DC, HIGH))
#define EPD_BUSY 3
#define EPD_RESET 4
#define EPD_DC 5
#define EPD_CS 10
#define SD_CS 8
#define VRES 300
#define HRES 400
#define WAIT_BUSY while (0 != digitalRead(EPD_BUSY))
//=============================================================================
//this function will take in a byte and send it to the display with the
//command bit low for command transmission
void writeCMD(uint8_t command)
{
ePaper_DC_0;
ePaper_CS_0;
SPI.transfer(command);
ePaper_CS_1;
}
//this function will take in a byte and send it to the display with the
//command bit high for data transmission
void writeData(uint8_t data)
{
ePaper_DC_1;
ePaper_CS_0;
SPI.transfer(data);
ePaper_CS_1;
}
//===========================================================================
void fullUpdate(void)
{
//
writeCMD(0x22);
writeData(0xf7);
writeCMD(0x20);
}
void partialUpdate(void)
{
//
writeCMD(0x22);
writeData(0xff);
writeCMD(0x20);
}
//===========================================================================
void setup(void)
{
//Debug port / Arduino Serial Monitor (optional)
Serial.begin(9600);
delay (1000);
Serial.println("setup started");
// Configure the pin directions
pinMode(EPD_CS, OUTPUT);
pinMode(EPD_RESET, OUTPUT);
pinMode(EPD_DC, OUTPUT);
pinMode(EPD_BUSY, INPUT);
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, LOW);
if (!SD.begin(SD_CS))
{
Serial.println("SD could not initialize");
}
//Set up SPI interface
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
SPI.begin();
initEPD();
Serial.println("setup complete");
}
//================================================================================
void initEPD()
{
//-----------------------------------------------------------------------------
//more detail on the following commands and additional commands not used here
//can be found on the CFAP176264A0-0270 datasheet on the Crystalfontz website
//-----------------------------------------------------------------------------
//reset driver
ePaper_RST_0;
delay(40);
ePaper_RST_1;
delay(40);
//Software Reset
WAIT_BUSY;
writeCMD(0x12);
WAIT_BUSY;
//Get out of deep sleep if we're there already
writeCMD(0x10);
writeData(0x00);
//Driver Output Control
writeCMD(0x01);
writeData(0xf9);
writeData(0x00);
writeData(0x00);
//Data Entry mode setting
writeCMD(0x11);
writeData(0x01);
//Set RAM X - address Start / End position
writeCMD(0x44);
writeData(0x00);
writeData(0x0F);
//Set RAM Y - address Start / End position
writeCMD(0x45);
writeData(0xF9);
writeData(0x00);
writeData(0x00);
writeData(0x00);
//Border Waveform Control
writeCMD(0x3C);
writeData(0x05);
//Display Update Control 1
writeCMD(0x21);
writeData(0x00);
writeData(0x80);
//Temperature Sensor Control
writeCMD(0x18);
writeData(0x80);
// Set RAM X and RAM Y address counter
writeCMD(0x4E);
writeData(0x00);
writeCMD(0x4F);
writeData(0xF9);
writeData(0x00);
WAIT_BUSY;
}
//================================================================================
void partialUpdateSolid(uint8_t x1, uint8_t y1, uint16_t x2, uint16_t y2, uint8_t color)
{
//Border Waveform Control
writeCMD(0x3C);
writeData(0x80);
//Set RAM X - address Start / End position
writeCMD(0x44);
writeData(x1);
writeData(x2);
//Set RAM Y - address Start / End position
writeCMD(0x45);
writeData(y1 & 0xff);
writeData(y1 >> 8);
writeData(y2 & 0xff);
writeData(y2 >> 8);
// Set RAM X and RAM Y address counter
writeCMD(0x4E);
writeData(x1);
writeCMD(0x4F);
writeData(y1 & 0xff);
writeData(y1 >> 8);
writeCMD(0x24);
int i;
int h;
for (h = 0; h < y2 - y1; h++)
{
for (i = 0; i < (x2 - x1) / 8; i++)
{
writeData(color);
}
}
//partial refresh of the same area as the partial update
partialUpdate();
WAIT_BUSY;
initEPD();
}
//================================================================================
void setBaseMap(const uint8_t *holder)
{
writeCMD(0x24); //Write Black and White image to RAM
for (int i = 0; i < MONO_ARRAY_SIZE; i++)
{
writeData(pgm_read_byte(&holder[i]));
}
writeCMD(0x26); //Write Black and White image to RAM
for (int i = 0; i < MONO_ARRAY_SIZE; i++)
{
writeData(pgm_read_byte(&holder[i]));
}
fullUpdate();
}
//================================================================================
void partialUpdateCharacters(const uint8_t *holder)
{
//x1 must be divisible by 8
uint16_t x1 = 0;
uint16_t y1 = 100;
uint16_t x2 = x1 + (64 / 8) - 1;
uint16_t y2 = y1 + (58) - 1;
//reset driver
ePaper_RST_0;
delay(40);
ePaper_RST_1;
delay(40);
//Border Waveform Control
writeCMD(0x3C);
writeData(0x80);
//Set RAM X - address Start / End position
writeCMD(0x44);
writeData(x1);
writeData(x2);
//Set RAM Y - address Start / End position
writeCMD(0x45);
writeData(y1 & 0xff);
writeData(y1 >> 8);
writeData(y2 & 0xff);
writeData(y2 >> 8);
// Set RAM X and RAM Y address counter
writeCMD(0x4E);
writeData(x1);
writeCMD(0x4F);
writeData(y1 & 0xff);
writeData(y1 >> 8);
writeCMD(0x24);
int i;
int h;
for (h = 0; h <= y2 - y1; h++)
{
for (i = 0; i < (x2 - x1 + 1); i++)
{
writeData(~pgm_read_byte(&holder[i + h * 8]));
}
}
//partial refresh of the same area as the partial update
partialUpdate();
WAIT_BUSY;
}
//================================================================================
void show_BMPs_in_root(void)
{
File
root_dir;
root_dir = SD.open("/");
if (0 == root_dir)
{
Serial.println("show_BMPs_in_root: Can't open \"root\"");
return;
}
File
bmp_file;
while (1)
{
bmp_file = root_dir.openNextFile();
Serial.println(bmp_file);
if (0 == bmp_file)
{
// no more files, break out of while()
// root_dir will be closed below.
break;
}
//Skip directories (what about volume name?)
if (0 == bmp_file.isDirectory())
{
//The file name must include ".BMP"
if (0 != strstr(bmp_file.name(), ".BMP"))
{
Serial.println(bmp_file.name());
//The BMP must be exactly 36918 long
//(this is correct for182x96, 24-bit)
uint32_t size = bmp_file.size();
Serial.println(size);
if ((uint32_t)HRES * VRES * 3 + 50 <= size <= (uint32_t)HRES * VRES * 3 + 60)
{
Serial.println("in final loop");
//Make sure the display is not busy before starting a new command.
WAIT_BUSY;
//Select the controller
writeCMD(0x13);
//Jump over BMP header
bmp_file.seek(54);
//grab one row of pixels from the SD card at a time
static uint8_t one_line[HRES / 2 * 3];
for (int line = 0; line < VRES * 2; line++)
{
//Set the LCD to the left of this line. BMPs store data
//to have the image drawn from the other end, uncomment the line below
//read a line from the SD card
bmp_file.read(one_line, HRES / 2 * 3);
//send the line to the display
send_pixels_BW(HRES / 2 * 3, one_line);
}
Serial.println("refreshing......");
//Write the command: Display Refresh (DRF)
fullUpdate();
//Make sure the display is not busy before starting a new command.
WAIT_BUSY;
Serial.print(" complete");
//Give a bit to let them see it
delay(3000);
}
}
}
//Release the BMP file handle
bmp_file.close();
}
//Release the root directory file handle
root_dir.close();
}
//================================================================================
void Load_Flash_Image_To_Display_RAM_RLE(uint16_t width_pixels,
uint16_t height_pixels,
const uint8_t *BW_image)
{
//Index into *image, that works with pgm_read_byte()
uint8_t count = 0;
//Get width_bytes from width_pixel, rounding up
uint8_t
width_bytes;
width_bytes = (width_pixels + 7) >> 3;
//Make sure the display is not busy before starting a new command.
WAIT_BUSY;
//Select the controller
ePaper_CS_0;
//Aim at the command register
ePaper_DC_0;
// Write RAM (Black White) / RAM 0x24
// After this command, data entries will be
// written into the BW RAM until another
// command is written. Address pointers will
// advance accordingly
SPI.transfer(0x24);
//Pump out the data.
ePaper_DC_1;
count = 0;
for (int i = 0; i < MONO_ARRAY_SIZE; i = i + 2)
{
count = pgm_read_byte(&BW_image[i]);
for (uint8_t j = 0; j < count; j++)
SPI.transfer(pgm_read_byte(&BW_image[i + 1]));
}
fullUpdate();
//Deslect the controller
ePaper_CS_1;
}
//================================================================================
void Load_Flash_Image_To_Display_RAM(uint16_t width_pixels,
uint16_t height_pixels,
const uint8_t *BW_image)
{
//Index into *image, that works with pgm_read_byte()
uint8_t count = 0;
//Get width_bytes from width_pixel, rounding up
uint8_t
width_bytes;
width_bytes = (width_pixels + 7) >> 3;
//Make sure the display is not busy before starting a new command.
WAIT_BUSY;
//Select the controller
ePaper_CS_0;
//Aim at the command register
ePaper_DC_0;
// Write RAM (Black White) / RAM 0x24
// After this command, data entries will be
// written into the BW RAM until another
// command is written. Address pointers will
// advance accordingly
SPI.transfer(0x24);
//Pump out the data.
ePaper_DC_1;
count = 0;
for (int i = 0; i < MONO_ARRAY_SIZE; i++)
{
SPI.transfer(pgm_read_byte(&BW_image[i]));
}
fullUpdate();
//Deslect the controller
ePaper_CS_1;
}
//================================================================================
void send_pixels_BW(uint16_t byteCount, uint8_t *dataPtr)
{
uint8_t data;
uint8_t red;
uint8_t green;
uint8_t blue;
while (byteCount != 0)
{
uint8_t data = 0;
red = *dataPtr;
dataPtr++;
byteCount--;
green = *dataPtr;
dataPtr++;
byteCount--;
blue = *dataPtr;
dataPtr++;
byteCount--;
if (150 > ((red * .21) + (green * .72) + (blue * .07)))
{
data = data | 0x01;
}
for (uint8_t i = 0; i < 7; i++)
{
red = *dataPtr;
dataPtr++;
byteCount--;
green = *dataPtr;
dataPtr++;
byteCount--;
blue = *dataPtr;
dataPtr++;
byteCount--;
data = data << 1;
if (127 > ((red * .21) + (green * .72) + (blue * .07)))
{
data = data | 0x01;
}
else
{
data = data & 0xFE;
}
}
writeData(data);
}
}
void outDeepSleep()
{
//Software Reset
WAIT_BUSY;
writeCMD(0x12);
WAIT_BUSY;
writeCMD(0x10);
writeData(0x00);
}
void deepSleep()
{
writeCMD(0x10);
writeData(0x01);
}
//=============================================================================
#define SHUTDOWN_BETWEEN_UPDATES (0)
#define waittime 5000
#define splashscreen 1
#define partialUpdate 1
#define showBMPs 0
#define black 1
#define white 1
void loop()
{
Serial.println("top of loop");
#if splashscreen
initEPD();
//load an image to the display
Load_Flash_Image_To_Display_RAM(HRES, VRES, Mono_1BPP);
Serial.print("refreshing . . . ");
WAIT_BUSY;
Serial.println("refresh complete");
//for maximum power conservation, power off the EPD
delay(waittime);
#endif
#if partialUpdate
initEPD();
setBaseMap(Mono_1BPP);
WAIT_BUSY;
delay(100);
partialUpdateCharacters(Mono_Letter_C);
partialUpdateCharacters(Mono_Letter_F);
partialUpdateCharacters(Mono_Letter_A);
partialUpdateCharacters(Mono_Letter_P);
delay(waittime);
#endif
#if showBMPs
//BMPs are inverted
initEPD();
Epaper_Write_Command(0x01); //Driver output control
Epaper_Write_Data(0xF9);
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x01);
show_BMPs_in_root();
delay(waittime);
//flip the display back to normal
Epaper_Write_Command(0x01); //Driver output control
Epaper_Write_Data(0xF9);
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x00);
#endif
#if black
initEPD();
//Make sure the display is not busy before starting a new command.
WAIT_BUSY;
//Select the controller
ePaper_CS_0;
//Aim at the command register
ePaper_DC_0;
// Write RAM (Black White) / RAM 0x24
// After this command, data entries will be
// written into the BW RAM until another
// command is written. Address pointers will
// advance accordingly
SPI.transfer(0x24);
//Pump out the data.
ePaper_DC_1;
for (int i = 0; i < MONO_ARRAY_SIZE; i++)
{
SPI.transfer(0xff);
}
fullUpdate();
//Deslect the controller
ePaper_CS_1;
delay(waittime);
#endif
#if white
initEPD();
//Make sure the display is not busy before starting a new command.
WAIT_BUSY;
//Select the controller
ePaper_CS_0;
//Aim at the command register
ePaper_DC_0;
// Write RAM (Black White) / RAM 0x24
// After this command, data entries will be
// written into the BW RAM until another
// command is written. Address pointers will
// advance accordingly
SPI.transfer(0x24);
//Pump out the data.
ePaper_DC_1;
for (int i = 0; i < MONO_ARRAY_SIZE; i++)
{
SPI.transfer(0x00);
}
fullUpdate();
//Deslect the controller
ePaper_CS_1;
delay(waittime);
#endif
}
//=============================================================================
here is the compiler output
FQBN: Seeeduino:nrf52:xiaonRF52840Sense
Using board 'xiaonRF52840Sense' from platform in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\nrf52\1.1.1
Using core 'nRF5' from platform in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\nrf52\1.1.1
Linking everything together...
"C:\\Users\\Dude\\AppData\\Local\\Arduino15\\packages\\Seeeduino\\tools\\arm-none-eabi-gcc\\9-2019q4/bin/arm-none-eabi-gcc" "-LC:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\5F57683B010A56727E94AB4AF4618B60
"C:\\Users\\Dude\\AppData\\Local\\Arduino15\\packages\\Seeeduino\\hardware\\nrf52\\1.1.1/tools/adafruit-nrfutil/win32/adafruit-nrfutil.exe" dfu genpkg --dev-type 0x0052 --sd-req 0x0123 --application "C:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\5F57683B010A56727E94AB4AF4618B60/CFAP122250A20213.ino.hex" "C:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\5F57683B010A56727E94AB4AF4618B60/CFAP122250A20213.ino.zip"
Zip created at C:\Users\Dude\AppData\Local\Temp\arduino\sketches\5F57683B010A56727E94AB4AF4618B60/CFAP122250A20213.ino.zip
Using library epd4in2 at version 1.0 in folder: D:\Arduino_projects\libraries\epd4in2-demo
Using library SPI at version 1.0 in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\nrf52\1.1.1\libraries\SPI
Using library SD at version 1.2.4 in folder: C:\Users\Dude\AppData\Local\Arduino15\libraries\SD
Using library Adafruit TinyUSB Library at version 1.7.0 in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\nrf52\1.1.1\libraries\Adafruit_TinyUSB_Arduino
"C:\\Users\\Dude\\AppData\\Local\\Arduino15\\packages\\Seeeduino\\tools\\arm-none-eabi-gcc\\9-2019q4/bin/arm-none-eabi-size" -A "C:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\5F57683B010A56727E94AB4AF4618B60/CFAP122250A20213.ino.elf"
Sketch uses 58220 bytes (7%) of program storage space. Maximum is 811008 bytes.
Global variables use 7912 bytes (3%) of dynamic memory, leaving 229656 bytes for local variables. Maximum is 237568 bytes.
Serial output looks like this.
SD could not initialize
setup complete
top of loop
refreshing . . . refresh complete
top of loop
refreshing . . . refresh complete
top of loop
refreshing . . . refresh complete
top of loop
refreshing . . . refresh complete
HTH
GL PJ
Nice Display for sure.!
That’s neat but I’m using the Xiao SAMD21 board.
Not sure about the code compatibility
Hi there,
e-Paper Xiao Nrf52840 Sense
SIGNAL(color) NAME PIN PORT
--------------------------------------
BUSY Purp D3 4 P0.29
RST White D4 (SDA) 5 P0.05
DC Green D5 (SCL) 6 P0.04
CS Orange D7 (RXD) 8 P1.12
CLK Yellow D8 (SCLK) 9 P1.13
DIN BLUE D10 (MOSI) 11 P1.15
GND BROWN GND 13
VCC GRAY 3V3 12
So, Yes solid , FAST display, super low power too and beside the Crystal Fonts Demo, I was able to also use the LINK on the 4.2" Seeed sales page Example code for the “Good Display” brand and once I set the correct pins it worked AOK.
This is to show they are ALL the same as far as E-paper goes. Waveshare makes the display “code compatibility” will only come down to 2 things
Memory & Pin configuration. So maybe start with the Examples on the Sales pages and Post your progress. Seems as if you’re not having enough ram? 32K isn’t allot.
HTH
GL PJ
FWIW there are a multitude of LIBRARY’s as well as examples that work GDEY042T81,GDEW042T2 4.2" b/w , CFAP122250A20213 & CFAP400300A0-420
Small update: I got the 4.2-inch e-paper display to work with the Xiao samd21 but only about 50% of the time which is a bit strange. What I mean by 50% is that if you unplug the power supply to the Xiao and plug it back in sometimes the display works and other times it doesn’t. This is a rough approximation. However, it only works when supplied by the Xiao’s 5V pin, not 3.3V. With 3.3V it doesn’t ever function.
Interestingly, I got the Xiao to work flawlessly with the Waveshare 2.9-inch and 1.54-inch e-paper displays. Also only while supplied with 5V.
#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold9pt7b.h>
// Pin configuration for Seeeduino Xiao SAMD21
// Display Xiao pin #
// BUSY -> 1
// RST -> 2
// DC -> 3
// CS -> 4
// CLK -> 8
// DIN -> 10
// GND -> GND
// VCC -> 5V
#define EPD_CS D4
#define EPD_DC D3
#define EPD_RST D2
#define EPD_BUSY D1
// 4.2 inch e-paper
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
// 2.9 inch e-paper
// GxEPD2_BW<GxEPD2_290_T94_V2, GxEPD2_290_T94_V2::HEIGHT> display(GxEPD2_290_T94_V2(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
// 1.54 inch e-paper
// GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
void setup() {
Serial.begin(9600);
display.init();
display.setRotation(1);
}
void loop() {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(10, 50);
display.print("Hello, World!");
display.display();
delay(1000);
display.fillScreen(GxEPD_WHITE);
display.display();
delay(1000);
}