夏休みの仕上げとして、XIAOと小型カラー液晶で作ったフォトフレームの動画アップしました。
--
21.04.21 追記
あまりキレイではありませんがスケッチです。無保証です。著作権は留保しますが、改変などご自由にどうぞ。
回路(結線)はスケッチと XIAOと1.8インチ小型液晶で小型フォトフレーム をご参照ください。タッチスイッチのピンは、スケッチ内に記載。
// 2020.08.19 naka // Small Digital Photo frame (Signage) // #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library #include <SdFat.h> // SD card & FAT filesystem library #include <Adafruit_ImageReader.h> // Image-reading functions #include <FlashAsEEPROM.h> // XIAOにはEEPROMがないのでflashをEEPROMのように使うライブラリ #include <FlashStorage.h> #define SD_CS 7 // SD card chip select #define TFT_CS 4 // TFT select pin #define TFT_DC 6 // TFT data/command pin #define TFT_RST 5 // Or set to -1 and connect TFT RST to Arduino reset pin #define TOUCHSW_1 2 #define TOUCHSW_2 3 #define FILENAME_SIZE 32 #define B_SIZE 32 SdFat SD; // SD card filesystem Adafruit_ImageReader reader(SD); // Image-reader object, pass in SD filesys Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); File root; int play; int interval; #define MAX_FILE 50 char file_tbl[MAX_FILE][FILENAME_SIZE]; int file_num; void setup(void) { // i/oピン設定 pinMode(TOUCHSW_1,INPUT); pinMode(TOUCHSW_2,INPUT); tft.initR(INITR_BLACKTAB); // Initialize screen tft.fillScreen(ST77XX_WHITE); tft.setRotation(3); if(!SD.begin(SD_CS, SD_SCK_MHZ(10))) { message("SD card error"); while(1); } read_flash(); // 設定値 (play,intervalをflashから読み出す) ImageReturnCode stat = reader.drawBMP("amazon.bmp", tft, 0, 0); delay(5000); // ファイル名一覧を取り出す int i_file; char filename[FILENAME_SIZE]; root = SD.open("/"); // rootにあるファイルのみ表示対象 file_num = 0; while(get_next_file_name(root,filename,FILENAME_SIZE)) { if (strcmp(filename,"amazon.bmp")!=0) { strcpy(file_tbl[file_num++],filename); if (file_num>=MAX_FILE) break; } } // for (int i=0;i<file_num;i++) { // Serial.print(file_tbl[i]); // Serial.print("\n"); // } qsort(file_tbl,file_num,sizeof(file_tbl[0]),compchar); // Serial.print("Sorted\n"); // for (int i=0;i<file_num;i++) { // Serial.print(file_tbl[i]); // Serial.print("\n"); // } char buff[30]; sprintf(buff,"bmp file number : %d",file_num); message(buff); delay(2000); } void loop() { char filename[FILENAME_SIZE]; char buff[B_SIZE]; static int i_file = 0; if (play==0) i_file = rand()%file_num; ImageReturnCode stat = reader.drawBMP(file_tbl[i_file], tft, 0, 0); if (stat) { // 読めないbmpファイルフォーマット sprintf(buff,"Not support %s",filename); message(buff); } int next = check_touchsw(); // 3秒表示 if (next==1) { i_file--; if (i_file<0) i_file = file_num - 1; } else { i_file++; if (i_file>=file_num) i_file = 0; } } int get_next_file_name(File dir,char *buff,int size) { File entry; while(1) { entry = root.openNextFile(); if (!entry) { // おしまい return(0); } if (!entry.isDirectory()) { // ファイルなら拡張子を確認してbmpならbreak entry.getName(buff,size); String fileName = String(buff); String ext = fileName.substring(fileName.lastIndexOf('.')); if (ext==".bmp" || ext==".BMP") { break; } } else { // dirならクローズして次のエントリ entry.close(); } } entry.close(); return (1); } void message(char* text) { tft.fillRect(0,tft.height()-71, 159,10, ST77XX_WHITE); // 消去 tft.setCursor(3,tft.height()-70); tft.setTextColor(ST77XX_RED); tft.setTextWrap(true); tft.setTextSize(1); tft.print(text); } int check_touchsw() { static unsigned int int_time[6] = {0,1000,3000,10000,30000,60000}; unsigned int time_s = millis(); while(1) { // touch swが押されているか if (digitalRead(TOUCHSW_1)==1 || digitalRead(TOUCHSW_2)==1) { // 押されている delay(100); // 同時押し確認 if (digitalRead(TOUCHSW_1)==1 && digitalRead(TOUCHSW_2)==1) { // 同時 select_menu(); return(0); } else if (digitalRead(TOUCHSW_1)==1) { return(1); } else if (digitalRead(TOUCHSW_2)==1) { return(2); } } else { if (interval!=0) { if ( (millis() - time_s) > int_time[interval] ) { // interval時間が経過した return (0); } } } } } void select_menu() { unsigned int pretime = 0; menu(); while(digitalRead(TOUCHSW_1)==1 || digitalRead(TOUCHSW_2)==1); // 離されるまで待つ disp_triangle_play(play,0); disp_triangle_interval(interval,0); while(1) { if ((millis()-pretime)>300) { disp_triangle_play(play,1); // blink=toggle pretime = millis(); } if (digitalRead(TOUCHSW_2)==1) { play++; if (play>1) play = 0; disp_triangle_play(play,1); while(digitalRead(TOUCHSW_2)==1); // 離されるまで待つ } if (digitalRead(TOUCHSW_1)==1) { while(digitalRead(TOUCHSW_1)==1); // 離されるまで待つ break; } } disp_triangle_play(play,0); // disp_triangle_interval(interval,0); // 1:blink while(1) { if ((millis()-pretime)>300) { disp_triangle_interval(interval,1); // blink=toggle pretime = millis(); } if (digitalRead(TOUCHSW_2)==1) { interval++; if (interval>5) interval = 0; disp_triangle_interval(interval,1); while(digitalRead(TOUCHSW_2)==1); // 離されるまで待つ } if (digitalRead(TOUCHSW_1)==1) { while(digitalRead(TOUCHSW_1)==1); // 離されるまで待つ break; } } disp_triangle_interval(interval,0); write_flash(); // 設定をflashに書き込む(書き込み回数制限10,000位) } int compchar(const void* left, const void* right) { char *left_char = (char *)left; char *right_char = (char *)right; return strcmp( left_char, right_char ); } void menu() { tft.fillScreen(ST77XX_WHITE); tft.setTextColor(ST77XX_BLUE); tft.setTextSize(1); tft.setCursor(20,tft.height()-120); tft.print("PLAY"); tft.setCursor(30,tft.height()-110); tft.print("random"); tft.setCursor(30,tft.height()-100); tft.print("sort"); tft.setCursor(20,tft.height()-80); tft.print("INTERVAL"); tft.setCursor(30,tft.height()-70); tft.print("manual"); tft.setCursor(30,tft.height()-60); tft.print(" 1 sec"); tft.setCursor(30,tft.height()-50); tft.print(" 3 sec"); tft.setCursor(30,tft.height()-40); tft.print("10 sec"); tft.setCursor(30,tft.height()-30); tft.print("30 sec"); tft.setCursor(30,tft.height()-20); tft.print("60 sec"); } void disp_triangle_play(uint16_t play,int blink) { static uint16_t preplay = 0; static int toggle = 0; uint16_t x1,y1,x2,y2,x3,y3; toggle ^= blink; if (blink==0 || toggle==1) { x1 = 20, y1 = tft.height() - (111 - preplay * 10); x2 = x1+4, y2 = y1 + 4; x3 = x1, y3 = y1 + 8; tft.fillTriangle(x1,y1,x2,y2,x3,y3,ST77XX_WHITE); // clear previous triangle } if (blink==0 || toggle==0) { x1 = 20, y1 = y1 = tft.height() - (111 - play * 10); x2 = x1+4, y2 = y1 + 4; x3 = x1, y3 = y1 + 8; tft.fillTriangle(x1,y1,x2,y2,x3,y3,ST77XX_RED); } preplay = play; } void disp_triangle_interval(uint16_t interval,int blink) { static uint16_t preint = 0; static int toggle = 0; uint16_t x1,y1,x2,y2,x3,y3; toggle ^= blink; if (blink==0 || toggle==1) { x1 = 20, y1 = tft.height() - (71 - preint * 10); x2 = x1+4, y2 = y1 + 4; x3 = x1, y3 = y1 + 8; tft.fillTriangle(x1,y1,x2,y2,x3,y3,ST77XX_WHITE); // clear previous triangle } if (blink==0 || toggle==0) { x1 = 20, y1 = y1 = tft.height() - (71 - interval * 10);; x2 = x1+4, y2 = y1 + 4; x3 = x1, y3 = y1 + 8; tft.fillTriangle(x1,y1,x2,y2,x3,y3,ST77XX_RED); } preint = interval; } void read_flash() { // FlashAsEEPROM を利用 if (EEPROM.isValid()) { play = (int)EEPROM.read(0); // play interval = (int)EEPROM.read(1); // interval } else { // 一度も書き込まれていないので初期値として以下を設定 play = 0; // random interval = 0; // manual } } void write_flash() { // FlashAsEEPROM を利用 EEPROM.write(0,play); EEPROM.write(1,interval); EEPROM.commit(); }
0 件のコメント:
コメントを投稿