黄土马家

Ink screen card ePaper_card

 
Overview

As we all know, ink screen cards are a very popular term recently. So what exactly is the ink screen card? I believe everyone is familiar with ink screen cards. Ink screen cards are what we often encounter every day, but what are ink screen cards? Now let the editor take you to understand what the ink screen card is all about. In fact, not many people knew about ink screen cards before, but recently due to the rising popularity, ink screen cards have attracted everyone's attention. You may be surprised, why are ink screen cards like this? Why are ink screen cards so popular? But this is the fact, and the editor was very surprised. I hope this content carefully compiled by the editor can help you. This teaching period is over. If you like it, you can like it to express your support for the editor. Welcome to discuss with the editor in the comments below~


Demo video: https://www.bilibili.com/video/BV1MT4y1f7yF

Why this project

Screenshot 2021-09-29 142238.pngI have been paying attention to the NFC business card project of Wild Iron Man for a long time ( video link ). Unfortunately, I have not had enough knowledge reserves and raw materials, and the project has been stuck at the step of creating a new folder (to put it bluntly, I am lazy~)

Then, a few days ago, I bought some pretty good ink screens from Lao Wang’s house. The quality is as shown in the picture. I think it’s okay. I bought 6 pieces and 3 of them turned on. The investment success rate is 50-50:

image.png

The driver board was found on an open source platform as a learning platform.

Similarities and Differences

The original plan was to realize 100% of the functions of Zhihuijun's NFC card: simulate access control cards, NFC upload data, etc. It's a pity that I can't find good learning materials for NFC transmission data (anyone with relevant information is welcome to leave a message in the comment area and learn together, thank you!). The NFC function cannot be implemented. What can be done about this? How to upload image data?

After thinking about it for a while, I decided to make an ink screen card that is different from Zhihui Jun. I gave up the NFC solution and used a microcontroller virtual U disk. Put the pictures to be displayed into the U disk (FLASH). The microcontroller reads the bmp image data and Displayed on the ink screen.

circuit board design

Once the requirements are determined, the circuit diagram will be ready.

Microcontroller

Driving both the ink screen and FLASH requires SPI. I used two SPI channels here. In order to prevent interference in data transmission, I later found that you can actually pay a little attention to programming. The two-channel data transmission will not interfere, so you can also use only one channel. SPI, just use two CS pins to control it separately, no need to go into details:

image.png

Ink screen

image.png

This solution is relatively mature.

power supply

Different from Zhihuijun's button battery, I chose a lithium battery power supply solution here, paired with an IP2312 charging chip, and the effect is still very good. Transfer data to the USB flash drive and charge the battery at the same time:

image.png

FLASH

Without going into details, you can refer to my last open source project: power meter

other

I won’t go into details about other LEDs and buttons.

Welding assembly

I designed a shell using solidworks, and it is very nice. The measurements are smaller than those of Zhihui Jun:

image.png

Circuit board diagram:

image.pngimage.pngAfter assembly:

image.png

Programming

I have put the burning file and the most critical bmp reading file in the attachment. You can pick it up if you need it. Corrections and corrections are welcome!

Let’s explain it a little bit:

First of all, we need to understand the bmp format. The most important thing is: 8-bit images use 1 byte to store one pixel, representing the gray value; 24-bit images use 3 bytes to store one pixel, and are stored in BGR order.

The following two functions first read the bmp image, including verifying the image attributes, reading the image bit depth, image length and width, etc.:

uint8_t ImgReadHeader(BITMAPFILEHEADER*Header, FIL* fp)
void ImgReadInfo(BMP_INFOHEADER* INFO, FIL* fp)

Zhihui Jun chose a black and white two-color ink screen. I made a slight improvement here and changed it to a black, white and red three-color ink screen. The disadvantage is that it cannot be refreshed locally (fast) and can only be refreshed globally (very slow), but considering the screen size It is very small and only refreshes a few times a day. The slow refresh rate is acceptable.

So the question is, how to display a picture on a three-color screen? Since each "microcapsule" (each small pixel displayed) of the ink screen can only display one color: either black, red or white. So it is necessary for us to divide a picture into two colors. I have been studying this for a long time and tried many solutions:

Q : Doesn’t bmp store the values ​​​​of the three colors of BGR? The R value of red must be relatively large. For example, wouldn’t it be better to define R>200 as red?

A : Indeed, bmp storage is rgb, but the ink screen display is not rgb. To be precise, it is CMYK, similar to a printer. You can read this blog post for details. If you have not understood it before, it may be a bit confusing. If you think about it carefully, you will understand. Therefore, the R values ​​of pure red and pure white are both 255. According to your judgment, they are both "red" and there is a bug.

Q : Damn, let me give you an example. Just improve it, for example, R>200 && G<50 && B<50 (If you don’t understand this, you can think about it carefully). Wouldn’t that be great!

A : Some pictures can indeed be displayed, but when it comes to some more complex pictures, they are unsightly. Such a threshold cannot solve the red to white gradient picture, and it is obvious that the two sides of the dividing line are uneven.

Q :. . .

After several attempts, the effect is still not ideal, mainly because the constraints on red in the RGB color space are not clear. Finally, I decided to use the HSV color space to solve this problem (because HSV has a relatively clear distinction between red), and used RGB to HSV function:

void RGB2HSV(uint8_t R, uint8_t G, uint8_t B,float * H, float * S, float * V)
{
    float max, min, delta=0;
    float r = R/255.0;
    float g = G/255.0;
    float b = B/255.0;

    max = max3(r, g, b);
    min = min3(r, g, b);
    delta = (max - min);

    if (fabs(delta)&lt;1e-3) {
        *H = 0;
    } else {
        if (fabs(r-max)&lt;1e-3) {
            *H = ((g-b)/delta)*60;
        } else if (fabs(g-max)&lt;1e-3) {
            *H = 120+(((b-r)/delta)*60);
        } else if (fabs(b-max)&lt;1e-3) {
            *H = 240 + (((r-g)/delta)*60);
        }
        if (*H &lt; 0)
            *H += 360;
    }

    if (fabs(max)&lt;1e-3)
        *S = 0;
    else
        *S = (float)(delta/max);
    *V = max;
}

Judgment function:

if( ((H>=0&amp;&amp;H&lt;=10)||(H>=156&amp;&amp;H&lt;=180)) &amp;&amp; S>=43 &amp;&amp; S&lt;=255 &amp;&amp; V>=46 &amp;&amp; V&lt;=255 )

Because my ink screen does not have gray scale , I decided to use the same dither function as Zhihui Jun, opencv source code picture:

image.png

Thanks to my teammates for porting it over:

uint8_t saturated_add(uint8_t val1, int8_t val2)
{
    int16_t val1_int = val1;
    int16_t val2_int = val2;
    int16_t tmp = val1_int + val2_int;

    if (tmp > 255)
    {
        return 255;
    }
    else if (tmp &lt; 0)
    {
        return 0;
    }
    else
    {
        return tmp;
    }
}

void dither(BMP_8 bmp8[][IMG_WIDTH])
{
    int err;
    int8_t a, b, c, d;
    for (int i = 0; i &lt; IMG_HEIGHT; i++)
    {
        for (int j = 0; j &lt; IMG_WIDTH; j++)
        {
            if (bmp8[i][j].gray_val > 127)
            {
                err = bmp8[i][j].gray_val - 255;
                bmp8[i][j].gray_val = 255;
            }
            else
            {
                err = bmp8[i][j].gray_val - 0;
                bmp8[i][j].gray_val = 0;
            }

            a = (err * 7) / 16;
            b = (err * 1) / 16;
            c = (err * 5) / 16;
            d = (err * 3) / 16;

            if ((i != (IMG_HEIGHT - 1)) &amp;&amp; (j != 0) &amp;&amp; (j != (IMG_WIDTH - 1)))
            {
                bmp8[i+0][j+1].gray_val = saturated_add(bmp8[i+0][j+1].gray_val , a);
                bmp8[i+1][j+1].gray_val  = saturated_add(bmp8[i+1][j+1].gray_val, b);
                bmp8[i+1][j+0].gray_val = saturated_add(bmp8[i+1][j+0].gray_val , c);
                bmp8[i+1][j-1].gray_val  = saturated_add( bmp8[i+1][j-1].gray_val, d);
            }
        }
    }
}

There is also a modulo function, which is equivalent to the modulo software we use:

image.png

void img2LCD(BMP_8 img_bmp8[IMG_HEIGHT][IMG_WIDTH],unsigned char gImage[]){
    uint16_t num=0;
    uint8_t data[8];
    uint8_t out;
    for (int i = 0; i &lt; IMG_HEIGHT; i++) {
        for (int j = 0; j &lt; IMG_WIDTH; ) {
            for(int k=0;k&lt;8;k++){
                if(img_bmp8[i][j].gray_val>128)
                    data[k]=1;
                else
                    data[k]=0;
                j++;
            }
            for(int k=0;k&lt;8;k++)
                out=out&lt;&lt;1|data[k];
            gImage[num]=out;
            num++;
            out=0;
        }
    }
}

In this way, we only need to put the image into the virtual USB disk and let the microcontroller automatically read, dither, and take the modulus. It is very nice and there is no need to worry about anything else.

Then there is the transplantation of FATFS. I won’t go into details on this. You can also refer to my last open source project: power meter power-X .

In this way, the whole process is very clear:

image.png


At this point, the project is completed~

The whole project is quite different from Zhihui Jun's, but the inspiration comes from him, thank you sir. Then abandoning NFC and using FASH storage also has advantages: it is simple to implement, and can store multiple pictures at the same time. A 4Mb flash can store hundreds of 152*152 bmp pictures.

Finally, I still hope that students who have good information about NFC can communicate in the comment area and learn together. Thanks for watching!



ZERO. 2021.9.29

参考设计图片
×
 
 
Search Datasheet?

Supported by EEWorld Datasheet

Forum More
Update:2025-06-19 03:10:41

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
community

Robot
development
community

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号