E-Paper Weather Display with Photon and IFTTT

Create a beautiful medium for weather information using Particle's cloud services and IFTTT.

E-Paper Weather Display with Photon and IFTTT

Things used in this project

 

Hardware components

HARDWARE LIST
1 Particle Photon with Headers
1 DFRobot E-Paper Display
1 Micro SD Card with Adapter
1 Micro USB Cable

Software apps and online services

 

IFTTT Maker service

Hand tools and fabrication machines

 

Hot glue gun (generic)

Story

If you have an E-Reader such as a Barnes & Noble NOOK or an Amazon Kindle then you're already familiar with e-paper. The e-paper display on your e-reader is what allows you to read it in direct sunlight without any glare. However, you also know that the e-paper screen takes a really long time to update. This means that you can't use it for gaming, but it's perfect for providing you with timely weather information wherever you need it! This super-simple project creates just that with minimal assembly and coding time. Let's dive in!

 

Step 1: The Parts

 

 

This project has only four components, all of which can be obtained from DFRobot. Check 'em out below:

 

E-Paper Display: https://www.dfrobot.com/product-1312.htmlMicro SD Card: https://www.dfrobot.com/product-1191.htmlParticle Photon: https://www.dfrobot.com/product-1324.htmlMicro USB Cable: https://www.dfrobot.com/product-770.html 

Other than a computer, this is literally all you need. Both the Photon and E-Paper display are highly integrated components, meaning that they need very little external support hardware to function. Go embedded systems! The display actually has its own integrated 32-bit microcontroller as a driver - this is part of the reason why it has a somewhat large price tag as compared to other displays.

 

 

 

Step 2: Assembly

 

 

Assembly is a piece of cake. The connections are as follows:

E-Paper -> Photon

RST -> UnconnectedWake_Up -> D2DIN -> TXDOUT -> RXGND -> GNDVCC -> 3V3 

There is some setup for your Photon that you need to do. Particle provides a great resource for this that you can check out here: https://docs.particle.io/guide/getting-started/start/photon/

 

That's it! Now let's move on to flashing your SD card with the required images for this project.

 

 

 

Step 3: Preparing Your SD Card

 

 

I'm going to preface this part by saying that if you really don't want to use an SD card, you don't have to. The display has a few MB of memory that you can use to store images. However, the program that allows you to load in these images is a bit, well, janky. I had a really tough time getting it to install on Windows 7, Windows 10, and macOS in wine bottler, so I decided to just give up and use the SD card. Here's how you can prepare yours:

 

Plug your micro SD card into the provided adapter and plug it into your computer. If you're on Mac you can utilize Disk Utility to easily format your card into the required FAT32 format. Name the card whatever you want. I'm sure Windows has a comprable program for formatting SD cards. If your card is new, it's also likely that it's already in FAT32. Download the .zip file linked in this step, and extract it. Load all those bitmaps onto the SD card, eject it, and put it in your display. You should now be good to go! 

Making your bitmap images in the correct format for the display is a little bit of trial and error. If you would like a tutorial on it let me know and I can create one. The biggest thing to remember is that the white pixels are actually the ones that are black on the display, and vice-versa.

 

Download Link: SD Card Package.zip

 

 

 

Step 4: IFTTT: Get Connecting!

 

 

The way your Photon will be getting weather information is from IFTTT. This mainly out of laziness on my part; IFTTT + Photon is practically a thing of magic and works with an extremely minimal amount of setup. I won't be explaining the process of signing up for an account or connecting the Particle service to your IFTTT account - Particle already has great documentation.

 

The basic flow for IFTTT is that Weather Underground sends data to your Photon at the same time every morning. This is done in two separate applets - one that sends over the high and low temperature information, and another that sends over the condition information.

 

If you don't already have it, add the Weather Underground service to IFTTT. It will ask you a bunch of questions that help it to deliver accurate weather information.

 

Now click the button to create a new applet. Choose Weather Underground as the service, and select Today's Weather Report as the trigger. Set the time to whenever you want your Particle to receive weather information each day. Select create trigger, then choose Particle for the "then" part of your applet. Select publish an event.

 

The name of your event should be something unique that no one else is likely to use. If it isn't unique enough, you will get events from other peoples' services. We'll be sending over the temperature information in this applet, so have it include something about temperature. A possibility could be "NewTemperatureInfoUpdate."

 

 

In the data field you need to use exactly what is shown in the above photo. This is, not including the quotes, "{{HighTempFahrenheit}},{{LowTempFahrenheit}}". If it is not exactly like this then your particle won't be able to process the incoming data. Lastly, change the event type to public, and create the applet.

 

 

 

This is only half of what needs to be done. You also need to create the applet that passes the condition information. The Weather Underground part is exactly the same. Create a new applet, and setup the Weather Underground service section in the same way. Choose Particle again for the "that" section, and select publish an event. It's the same deal for the name of your event. Make it unique, and something that has to do with condition. A possibility could be "GotNewConditionInformation"

 

In the data field of your event you need to have exactly the following (without quotes): "{{TodaysCondition}}". Press create, and you should be all set with IFTTT.

 

 

 

Step 5: Flashing Your Particle

 

 

Luckily for you I did all the complicated setup to get the E-Paper display to interface correctly with your Photon. All you need to do is click on this link and copy the Particle Build app: https://go.particle.io/shared_apps/5995bb8f077992ee5d000c79

 

Once the app is copied to your Particle account you can perform the final setup. The only parts of the code that you need to change are lines 30 and 31. Change the name of the event to be the event that you created inside of IFTTT, and you're done! Flash you Photon and with any luck the above screen should appear.

 

Once the set time of your applet passes the display will update with the correct weather info. To make this update interval more frequent all you need to do is create more applets with the same event name. The clock will update every minute automatically. To change the time zone you need to configure line 26 with your UTC offset.

 

 

 

Step 6: Final Thoughts

 

You can mount the display however you like. As shown in the video at the beginning of this tutorial, I glued my Photon to the back of my display. This has the added benefit of acting as a little kickstand to prop up the whole project!

 

If you have any questions don't hesitate to comment below or send me a message. You can check out my projects on my Hackster profile, my Maker Share profile, and my Instructables profile. I also have written a bunch of interesting blog posts. Read them on Medium.

Code

 

ParticleStationEpaper.ino

Arduino

CODE
#include "epd.h"

//Code produced by Alex Wulff - www.AlexWulff.com

void setup(void)
{
    //Initialize E-Paper display, set memory to flash card, change the font, and set the foreground and background colors.
    epd_init();
    epd_wakeup();
    epd_set_memory(MEM_TF);
	epd_set_color(BLACK, WHITE);
	epd_set_en_font(ASCII64);
	epd_clear();
	
	//Put the initial graphics on-screen
	epd_disp_bitmap("PRT.BMP", 475, 25);
	epd_disp_bitmap("BTM.BMP", 0, 324);
	epd_disp_string("No Data", 25, 25);
    epd_disp_string("High Temp: 00", 25, 100);
    epd_disp_string("Low Temp: 00", 25, 175);
    
    //The author of this library spelled update wrong. It bugs me, but not enough to go in and change it
	epd_udpate();
	
	// Set time zone to Eastern USA daylight saving time
    Time.zone(-4);
	displayTime();
    
    //Subscribe to the two actions from IFTTT. Change the string to be the name that you chose
    Particle.subscribe("NAME_OF_CONDITION_ACTION", conditionHandler);
    Particle.subscribe("NAME_OF_TEMP_ACTION", tempHandler);
    
}

//Is called when you receive temperature data
void tempHandler(const char *event, const char *data) {
    int high, low;
    
    //Retrieve the two temperature values from the string using C++'s sscanf() fct
    if (sscanf(data, "%d,%d", &high, &low) == 2) {
        
        //Create two strings with the temp values added in
        char highBuffer[64];
        char lowBuffer[64];
        sprintf(highBuffer, "High Temp:  %d", high);
        sprintf(lowBuffer, "Low Temp:  %d", low);
        
        //I don't want to clear the display, so I'm overwriting that line instead
        epd_disp_string("High Temp:      ", 25, 100);
        epd_disp_string("Low Temp:      ", 25, 175);
        epd_udpate();
        
        //Finally display the two strings
        epd_disp_string(highBuffer, 25, 100);
        epd_disp_string(lowBuffer, 25, 175);
        epd_udpate();
    }
    
    else {
        
        //This means there was an error. This probably happened because your action name wasn't unique enough and you're getting someone else's action
        epd_disp_string("Error w/ temp", 0, 450);
        epd_disp_string("                  ", 0, 525);
        epd_disp_string(data, 0, 525);
        epd_udpate();
    }
}

void conditionHandler(const char *event, const char *data) {
    
    //The width of spaces is small, so in order to clear the line I need a ton of them
    epd_disp_string("                                                ", 25, 50);
    epd_udpate();
    
    //Display the condition name
    epd_disp_string(data, 25, 25);
    
    //This matches the images on the SD card with specific conditions. All the conditions in that link
    //https://www.wunderground.com/weather/api/d/docs?d=resources/phrase-glossary&_ga=2.68020689.1328253466.1502822638-1300575137.1434505073&MR=1
    if(strstr(data, "Drizzle") != NULL || strstr(data, "Rain") != NULL) {
        epd_disp_bitmap("RAIN.BMP", 475, 25);
    }
    
    else if(strstr(data, "Clear") != NULL || strstr(data, "Sun") != NULL) {
        epd_disp_bitmap("SUN.BMP", 475, 25);
    }
    
    else if(strstr(data, "Part") != NULL) {
        epd_disp_bitmap("PRT.BMP", 475, 25);
    }
    
    else if(strstr(data, "Cloudy") != NULL) {
        epd_disp_bitmap("RAIN.BMP", 475, 25);
    }
    
    else if(strstr(data, "Freezing") != NULL || strstr(data, "Snow") != NULL) {
        epd_disp_bitmap("SNOW.BMP", 475, 25);
    }
    
    epd_udpate();
}

void displayTime() {
    //See http://strftime.org for formatting info. This displays the time.
    epd_disp_string(Time.format(Time.now(), "It's %I:%M%p."), 25, 250); //It's 12:57PM.
    epd_udpate();
}

int lastChecked = 0;

void loop() {
    
    //Every minute sync the clock with the cloud and update the time on the display.
    if (millis() - lastChecked > 60000) {
        Particle.syncTime();
        displayTime();
        lastChecked = millis();
    }
}

epd.h

C/C++

CODE
/*********************************************************************************************************
*
* File                : epd.h
* Hardware Environment: 
* Build Environment   : RealView MDK-ARM  Version: 4.74
* Version             : V1.0
* By                  : V
*
*                                  (c) Copyright 2005-2015, WaveShare
*                                       http://www.waveshare.net
*                                          All Rights Reserved
*
* 
* Please note: this library has been modified by Alex Wulff (www.AlexWulff.com)
* to be compatible for the Particle Photon. It is not in its original form.
*********************************************************************************************************/
#ifndef    EPD_H
  #define  EPD_H
	

#define    CMD_SIZE                           512	

/*
frame format
*/
#define    FRAME_B                            0xA5
#define    FRAME_E0                           0xCC
#define    FRAME_E1                           0x33
#define    FRAME_E2                           0xC3
#define    FRAME_E3                           0x3C


/*
color define
*/
#define    WHITE                              0x03
#define    GRAY                               0x02
#define    DARK_GRAY                          0x01
#define    BLACK                              0x00

/*
command define
*/
#define    CMD_HANDSHAKE                      0x00                                                     //handshake
#define    CMD_SET_BAUD                       0x01                                                     //set baud
#define    CMD_READ_BAUD                      0x02                                                     //read baud
#define    CMD_MEMORYMODE                     0x07                                                     //set memory mode
#define    CMD_STOPMODE                       0x08                                                     //enter stop mode 
#define    CMD_UPDATE                         0x0A                                                     //update
#define    CMD_SCREEN_ROTATION                0x0D                                                     //set screen rotation
#define    CMD_LOAD_FONT                      0x0E                                                     //load font
#define    CMD_LOAD_PIC                       0x0F                                                     //load picture

#define    CMD_SET_COLOR                      0x10                                                     //set color
#define    CMD_SET_EN_FONT                    0x1E                                                     //set english font
#define    CMD_SET_CH_FONT                    0x1F                                                     //set chinese font

#define    CMD_DRAW_PIXEL                     0x20                                                     //set pixel
#define    CMD_DRAW_LINE                      0x22                                                     //draw line
#define    CMD_FILL_RECT                      0x24                                                     //fill rectangle
#define    CMD_DRAW_CIRCLE                    0x26                                                     //draw circle
#define    CMD_FILL_CIRCLE                    0x27                                                     //fill circle
#define    CMD_DRAW_TRIANGLE                  0x28                                                     //draw triangle
#define    CMD_FILL_TRIANGLE                  0x29                                                     //fill triangle
#define    CMD_CLEAR                          0x2E                                                     //clear screen use back color

#define    CMD_DRAW_STRING                    0x30                                                     //draw string

#define    CMD_DRAW_BITMAP                    0x70                                                     //draw bitmap


/*
FONT
*/
#define    GBK32                              0x01
#define    GBK48                              0x02
#define    GBK64                              0x03
	
#define    ASCII32                            0x01
#define    ASCII48                            0x02
#define    ASCII64                            0x03



/*
Memory Mode
*/
#define    MEM_NAND                           0
#define    MEM_TF                             1

/*
set screen rotation
*/
#define    EPD_NORMAL                         0                                                        //screen normal
#define    EPD_INVERSION                      1                                                        //screen inversion      


void epd_init(void);
void epd_reset(void);
void epd_wakeup(void);

void epd_handshake(void);
void epd_set_memory(unsigned char mode);
void epd_enter_stopmode(void);
void epd_udpate(void);
void epd_screen_rotation(unsigned char mode);
void epd_load_font(void);
void epd_load_pic(void);


void epd_set_color(unsigned char color, unsigned char bkcolor);
void epd_set_en_font(unsigned char font);
void epd_set_ch_font(unsigned char font);

void epd_draw_pixel(int x0, int y0);
void epd_draw_line(int x0, int y0, int x1, int y1);
void epd_fill_rect(int x0, int y0, int x1, int y1);
void epd_draw_circle(int x0, int y0, int r);
void epd_fill_circle(int x0, int y0, int r);
void epd_draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2);
void epd_fill_triangle(int x0, int y0, int x1, int y1, int x2, int y2);
void epd_clear(void);

void epd_disp_char(unsigned char ch, int x0, int y0);
void epd_disp_string(const void * p, int x0, int y0);

void epd_disp_bitmap(const void * p, int x0, int y0);


	
#endif

epd.cpp

C/C++

CODE
/*********************************************************************************************************
*
* File                : epd.c
* Hardware Environment: 
* Build Environment   : RealView MDK-ARM  Version: 4.74
* Version             : V1.0
* By                  : V
*
*                                  (c) Copyright 2005-2014, WaveShare
*                                       http://www.waveshare.net
*                                          All Rights Reserved
*
* 
* Please note: this library has been modified by Alex Wulff (www.AlexWulff.com)
* to be compatible for the Particle Photon. It is not in its original form.
*********************************************************************************************************/
#include "epd.h"
#include "Particle.h"

const int wake_up = 2;
// const int reset = 3;


/*
command define
*/
static const unsigned char _cmd_handshake[8] = {0xA5, 0x00, 0x09, CMD_HANDSHAKE, 0xCC, 0x33, 0xC3, 0x3C};				//CMD_HANDSHAKE
static const unsigned char _cmd_read_baud[8] = {0xA5, 0x00, 0x09, CMD_READ_BAUD, 0xCC, 0x33, 0xC3, 0x3C};				//CMD_READ_BAUD
static const unsigned char _cmd_stopmode[8] = {0xA5, 0x00, 0x09, CMD_STOPMODE, 0xCC, 0x33, 0xC3, 0x3C}; 				//CMD_STOPMODE
static const unsigned char _cmd_update[8] = {0xA5, 0x00, 0x09, CMD_UPDATE, 0xCC, 0x33, 0xC3, 0x3C}; 					//CMD_UPDATE
static const unsigned char _cmd_load_font[8] = {0xA5, 0x00, 0x09, CMD_LOAD_FONT, 0xCC, 0x33, 0xC3, 0x3C};				//CMD_LOAD_FONT
static const unsigned char _cmd_load_pic[8] = {0xA5, 0x00, 0x09, CMD_LOAD_PIC, 0xCC, 0x33, 0xC3, 0x3C}; 				//CMD_LOAD_PIC




static unsigned char _cmd_buff[CMD_SIZE];



/*
private function
*/
static void _putchars(const unsigned char * ptr, int n);
static unsigned char _verify(const void * ptr, int n);



/*******************************************************************************
* Function Name  : static void _putchars(const unsigned char * ptr, int n)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
static void _putchars(const unsigned char * ptr, int n)
{
	int i, x;
	
	for(i = 0; i < n; i++)
	{
	    x = ptr[i];
		Serial1.write(x);
	}
}
/*******************************************************************************
* Function Name  : static unsigned char _verify(const void * ptr, int n)
* Description    : 
* Input          : ptr      
                   n        
* Output         : None
* Return         : 
*******************************************************************************/
static unsigned char _verify(const void * ptr, int n)
{
	int i;
	unsigned char * p = (unsigned char *)ptr;
	unsigned char result;
	
	for(i = 0, result = 0; i < n; i++)
	{
		result ^= p[i];
	}
	
	return result;
}




/*******************************************************************************
* Function Name  : void epd_init(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_init(void)
{
	Serial1.begin(115200);
	pinMode(wake_up, OUTPUT);
// 	pinMode(reset, OUTPUT);
}
/*******************************************************************************
* Function Name  : void epd_reset(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_reset(void)
{
	digitalWrite(reset, LOW);
	delayMicroseconds(10);
	digitalWrite(reset, HIGH);
	delayMicroseconds(500);
	digitalWrite(reset, LOW);
	delay(3000);
}
/*******************************************************************************
* Function Name  : void epd_init(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_wakeup(void)
{
	digitalWrite(wake_up, LOW);
	delayMicroseconds(10);
	digitalWrite(wake_up, HIGH);
	delayMicroseconds(500);
	digitalWrite(wake_up, LOW);
	delay(10);
}

/*******************************************************************************
* Function Name  : void epd_handshake(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_handshake(void)
{
	memcpy(_cmd_buff, _cmd_handshake, 8);
	_cmd_buff[8] = _verify(_cmd_buff, 8);
	
	_putchars(_cmd_buff, 9);
}
/*******************************************************************************
* Function Name  : void epd_set_baud(long baud)
* Description    : set uart baud
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_set_baud(long baud)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0D;	
	
	_cmd_buff[3] = CMD_SET_BAUD;	
	
	_cmd_buff[4] = (baud >> 24) & 0xFF;
	_cmd_buff[5] = (baud >> 16) & 0xFF;
	_cmd_buff[6] = (baud >> 8) & 0xFF;
	_cmd_buff[7] = baud & 0xFF;
	
	_cmd_buff[8] = FRAME_E0;
	_cmd_buff[9] = FRAME_E1;
	_cmd_buff[10] = FRAME_E2;
	_cmd_buff[11] = FRAME_E3;	
	_cmd_buff[12] = _verify(_cmd_buff, 12);
	
	_putchars(_cmd_buff, 13);	
	
	delay(10);	
	Serial1.begin(baud);
}
/*******************************************************************************
* Function Name  : void epd_read_baud(void)
* Description    : read uart baud
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_read_baud(void)
{
	memcpy(_cmd_buff, _cmd_read_baud, 8);
	_cmd_buff[8] = _verify(_cmd_buff, 8);
	
	_putchars(_cmd_buff, 9);
}
/*******************************************************************************
* Function Name  : void epd_set_memory(unsigned char mode)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_set_memory(unsigned char mode)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0A;	
	
	_cmd_buff[3] = CMD_MEMORYMODE;
	
	_cmd_buff[4] = mode;
	
	_cmd_buff[5] = FRAME_E0;
	_cmd_buff[6] = FRAME_E1;
	_cmd_buff[7] = FRAME_E2;
	_cmd_buff[8] = FRAME_E3;	
	_cmd_buff[9] = _verify(_cmd_buff, 9);
	
	_putchars(_cmd_buff, 10);		
}

/*******************************************************************************
* Function Name  : void epd_enter_stopmode(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_enter_stopmode(void)
{
	memcpy(_cmd_buff, _cmd_stopmode, 8);
	_cmd_buff[8] = _verify(_cmd_buff, 8);
	
	_putchars(_cmd_buff, 9);
}
/*******************************************************************************
* Function Name  : void epd_udpate(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_udpate(void)
{
	memcpy(_cmd_buff, _cmd_update, 8);
	_cmd_buff[8] = _verify(_cmd_buff, 8);
	
	_putchars(_cmd_buff, 9);
}
/*******************************************************************************
* Function Name  : void epd_screen_rotation(unsigned char mode)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_screen_rotation(unsigned char mode)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0A;	
	
	_cmd_buff[3] = CMD_SCREEN_ROTATION;
	
	_cmd_buff[4] = mode;
	
	_cmd_buff[5] = FRAME_E0;
	_cmd_buff[6] = FRAME_E1;
	_cmd_buff[7] = FRAME_E2;
	_cmd_buff[8] = FRAME_E3;	
	_cmd_buff[9] = _verify(_cmd_buff, 9);
	
	_putchars(_cmd_buff, 10);	
}
/*******************************************************************************
* Function Name  : void epd_load_font(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_load_font(void)
{
	memcpy(_cmd_buff, _cmd_load_font, 8);
	_cmd_buff[8] = _verify(_cmd_buff, 8);
	
	_putchars(_cmd_buff, 9);	
}
/*******************************************************************************
* Function Name  : void epd_load_pic(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_load_pic(void)
{
	memcpy(_cmd_buff, _cmd_load_pic, 8);
	_cmd_buff[8] = _verify(_cmd_buff, 8);
	
	_putchars(_cmd_buff, 9);
}
/*******************************************************************************
* Function Name  : void epd_set_color(unsigned char color, unsigned char bkcolor)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_set_color(unsigned char color, unsigned char bkcolor)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0B;
	
	_cmd_buff[3] = CMD_SET_COLOR;
	
	_cmd_buff[4] = color;
	_cmd_buff[5] = bkcolor;
	
	_cmd_buff[6] = FRAME_E0;
	_cmd_buff[7] = FRAME_E1;
	_cmd_buff[8] = FRAME_E2;
	_cmd_buff[9] = FRAME_E3;
	_cmd_buff[10] = _verify(_cmd_buff, 10);
	
	_putchars(_cmd_buff, 11);
}
/*******************************************************************************
* Function Name  : void epd_set_en_font(unsigned char font)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_set_en_font(unsigned char font)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0A;	
	
	_cmd_buff[3] = CMD_SET_EN_FONT;
	
	_cmd_buff[4] = font;
	
	_cmd_buff[5] = FRAME_E0;
	_cmd_buff[6] = FRAME_E1;
	_cmd_buff[7] = FRAME_E2;
	_cmd_buff[8] = FRAME_E3;	
	_cmd_buff[9] = _verify(_cmd_buff, 9);
	
	_putchars(_cmd_buff, 10);	
}
/*******************************************************************************
* Function Name  : void epd_set_ch_font(unsigned char font)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_set_ch_font(unsigned char font)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0A;	
	
	_cmd_buff[3] = CMD_SET_CH_FONT;
	
	_cmd_buff[4] = font;
	
	_cmd_buff[5] = FRAME_E0;
	_cmd_buff[6] = FRAME_E1;
	_cmd_buff[7] = FRAME_E2;
	_cmd_buff[8] = FRAME_E3;	
	_cmd_buff[9] = _verify(_cmd_buff, 9);
	
	_putchars(_cmd_buff, 10);
}
/*******************************************************************************
* Function Name  : void epd_draw_pixel(int x0, int y0)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_draw_pixel(int x0, int y0)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0D;	
	
	_cmd_buff[3] = CMD_DRAW_PIXEL;	
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	
	_cmd_buff[8] = FRAME_E0;
	_cmd_buff[9] = FRAME_E1;
	_cmd_buff[10] = FRAME_E2;
	_cmd_buff[11] = FRAME_E3;	
	_cmd_buff[12] = _verify(_cmd_buff, 12);
	
	_putchars(_cmd_buff, 13);
}
/*******************************************************************************
* Function Name  : void epd_draw_line(int x0, int y0, int x1, int y1)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_draw_line(int x0, int y0, int x1, int y1)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x11;	
	
	_cmd_buff[3] = CMD_DRAW_LINE;	
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	_cmd_buff[8] = (x1 >> 8) & 0xFF;
	_cmd_buff[9] = x1 & 0xFF;
	_cmd_buff[10] = (y1 >> 8) & 0xFF;
	_cmd_buff[11] = y1 & 0xFF;	
	
	_cmd_buff[12] = FRAME_E0;
	_cmd_buff[13] = FRAME_E1;
	_cmd_buff[14] = FRAME_E2;
	_cmd_buff[15] = FRAME_E3;	
	_cmd_buff[16] = _verify(_cmd_buff, 16);
	
	_putchars(_cmd_buff, 17);	
}
/*******************************************************************************
* Function Name  : void epd_fill_rect(int x0, int y0, int x1, int y1)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_fill_rect(int x0, int y0, int x1, int y1)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x11;	
	
	_cmd_buff[3] = CMD_FILL_RECT;	
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	_cmd_buff[8] = (x1 >> 8) & 0xFF;
	_cmd_buff[9] = x1 & 0xFF;
	_cmd_buff[10] = (y1 >> 8) & 0xFF;
	_cmd_buff[11] = y1 & 0xFF;	
	
	_cmd_buff[12] = FRAME_E0;
	_cmd_buff[13] = FRAME_E1;
	_cmd_buff[14] = FRAME_E2;
	_cmd_buff[15] = FRAME_E3;	
	_cmd_buff[16] = _verify(_cmd_buff, 16);
	
	_putchars(_cmd_buff, 17);		
}
/*******************************************************************************
* Function Name  : void epd_draw_circle(int x0, int y0, int r)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_draw_circle(int x0, int y0, int r)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0F;	
	
	_cmd_buff[3] = CMD_DRAW_CIRCLE;	
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	_cmd_buff[8] = (r >> 8) & 0xFF;
	_cmd_buff[9] = r & 0xFF;
	
	
	_cmd_buff[10] = FRAME_E0;
	_cmd_buff[11] = FRAME_E1;
	_cmd_buff[12] = FRAME_E2;
	_cmd_buff[13] = FRAME_E3;	
	_cmd_buff[14] = _verify(_cmd_buff, 14);
	
	_putchars(_cmd_buff, 15);
}
/*******************************************************************************
* Function Name  : void epd_fill_circle(int x0, int y0, int r)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_fill_circle(int x0, int y0, int r)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x0F;	
	
	_cmd_buff[3] = CMD_FILL_CIRCLE;	
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	_cmd_buff[8] = (r >> 8) & 0xFF;
	_cmd_buff[9] = r & 0xFF;
	
	
	_cmd_buff[10] = FRAME_E0;
	_cmd_buff[11] = FRAME_E1;
	_cmd_buff[12] = FRAME_E2;
	_cmd_buff[13] = FRAME_E3;	
	_cmd_buff[14] = _verify(_cmd_buff, 14);
	
	_putchars(_cmd_buff, 15);	
}
/*******************************************************************************
* Function Name  : void epd_draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x15;	
	
	_cmd_buff[3] = CMD_DRAW_TRIANGLE;	
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	_cmd_buff[8] = (x1 >> 8) & 0xFF;
	_cmd_buff[9] = x1 & 0xFF;
	_cmd_buff[10] = (y1 >> 8) & 0xFF;
	_cmd_buff[11] = y1 & 0xFF;	
	_cmd_buff[12] = (x2 >> 8) & 0xFF;
	_cmd_buff[13] = x2 & 0xFF;
	_cmd_buff[14] = (y2 >> 8) & 0xFF;
	_cmd_buff[15] = y2 & 0xFF;
	
	_cmd_buff[16] = FRAME_E0;
	_cmd_buff[17] = FRAME_E1;
	_cmd_buff[18] = FRAME_E2;
	_cmd_buff[19] = FRAME_E3;	
	_cmd_buff[20] = _verify(_cmd_buff, 20);
	
	_putchars(_cmd_buff, 21);		
}
/*******************************************************************************
* Function Name  : void epd_fill_triangle(int x0, int y0, int x1, int y1, int x2, int y2)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_fill_triangle(int x0, int y0, int x1, int y1, int x2, int y2)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x15;	
	
	_cmd_buff[3] = CMD_FILL_TRIANGLE;	
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	_cmd_buff[8] = (x1 >> 8) & 0xFF;
	_cmd_buff[9] = x1 & 0xFF;
	_cmd_buff[10] = (y1 >> 8) & 0xFF;
	_cmd_buff[11] = y1 & 0xFF;	
	_cmd_buff[12] = (x2 >> 8) & 0xFF;
	_cmd_buff[13] = x2 & 0xFF;
	_cmd_buff[14] = (y2 >> 8) & 0xFF;
	_cmd_buff[15] = y2 & 0xFF;
	
	_cmd_buff[16] = FRAME_E0;
	_cmd_buff[17] = FRAME_E1;
	_cmd_buff[18] = FRAME_E2;
	_cmd_buff[19] = FRAME_E3;	
	_cmd_buff[20] = _verify(_cmd_buff, 20);
	
	_putchars(_cmd_buff, 21);	
}
/*******************************************************************************
* Function Name  : void epd_clear(void)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_clear(void)
{
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = 0x00;
	_cmd_buff[2] = 0x09;	
	
	_cmd_buff[3] = CMD_CLEAR;
	
	_cmd_buff[4] = FRAME_E0;
	_cmd_buff[5] = FRAME_E1;
	_cmd_buff[6] = FRAME_E2;
	_cmd_buff[7] = FRAME_E3;	
	_cmd_buff[8] = _verify(_cmd_buff, 8);
	
	_putchars(_cmd_buff, 9);	
}

/*******************************************************************************
* Function Name  : void epd_disp_char(unsigned char ch, int x0, int y0);
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_disp_char(unsigned char ch, int x0, int y0)
{
	unsigned char buff[2];
	
	buff[0] = ch;
	buff[1] = 0;
	
	epd_disp_string(buff, x0, y0);
}
/*******************************************************************************
* Function Name  : void epd_disp_string(const void * p, int x0, int y0)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_disp_string(const void * p, int x0, int y0)
{
	int string_size;
	unsigned char * ptr = (unsigned char *)p;
	
	
	string_size = strlen((const char *)ptr);
	string_size += 14;
	
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = (string_size >> 8) & 0xFF;
	_cmd_buff[2] = string_size & 0xFF;
	
	_cmd_buff[3] = CMD_DRAW_STRING;
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	
	strcpy((char *)(&_cmd_buff[8]), (const char *)ptr);
	
	string_size -= 5;
	
	_cmd_buff[string_size] = FRAME_E0;
	_cmd_buff[string_size + 1] = FRAME_E1;
	_cmd_buff[string_size + 2] = FRAME_E2;
	_cmd_buff[string_size + 3] = FRAME_E3;
	_cmd_buff[string_size + 4] = _verify(_cmd_buff, string_size + 4);
	
	_putchars(_cmd_buff, string_size + 5);
}
/*******************************************************************************
* Function Name  : void epd_disp_bitmap(const void * p, int x0, int y0)
* Description    : 
* Input          : 
* Output         : None
* Return         : 
* Attention		   : None
*******************************************************************************/
void epd_disp_bitmap(const void * p, int x0, int y0)
{
	int string_size;
	unsigned char * ptr = (unsigned char *)p;
	
	string_size = strlen((const char *)ptr);
	string_size += 14;
	
	_cmd_buff[0] = FRAME_B;
	
	_cmd_buff[1] = (string_size >> 8) & 0xFF;
	_cmd_buff[2] = string_size & 0xFF;
	
	_cmd_buff[3] = CMD_DRAW_BITMAP;
	
	_cmd_buff[4] = (x0 >> 8) & 0xFF;
	_cmd_buff[5] = x0 & 0xFF;
	_cmd_buff[6] = (y0 >> 8) & 0xFF;
	_cmd_buff[7] = y0 & 0xFF;
	
	strcpy((char *)(&_cmd_buff[8]), (const char *)ptr);
	
	string_size -= 5;
	
	_cmd_buff[string_size] = FRAME_E0;
	_cmd_buff[string_size + 1] = FRAME_E1;
	_cmd_buff[string_size + 2] = FRAME_E2;
	_cmd_buff[string_size + 3] = FRAME_E3;
	_cmd_buff[string_size + 4] = _verify(_cmd_buff, string_size + 4);
	
	_putchars(_cmd_buff, string_size + 5);	
}

The article was first published in hackster, August 17, 2017

cr: https://www.hackster.io/AlexWulff/e-paper-weather-display-with-photon-and-ifttt-cc37a0

author: Alex Wulff

License
All Rights
Reserved
licensBg
0