Hi Andrew
I am new to this forum as I have just found your video on youtube with the nextion dialog demo
I have downloaded it from the nextion forum and modified it to work on my 7" display running a teensy 3.5 with built in SD card the demo runs ok with some tweaks to for my application,
But I can't get it to list the file list from the SD card, I have it listing them with the serial monitor with Serial.print(entry.name()); so it is reading the SD card but I can't find a way to get it to list the files and use them in the nextion
I'm probably missing something simple
would you be able to give me a sample of how to get the SD list to list on the nextion like it does with the demo static char's
As i'm using a teensy with built in SD card some of the commands are diferent to you have in the source code for this TV project you are doing I have had a look but still can't figure it out
this is test code I have so far that does not have any errors when compiling and runs and prints SD card file list to serial monitor
- Code: Select all
// Nextion UI - File Selection Dialog
// program by Andrew Davie (andrew@taswegian.com)
// released to public domain; drop me an email if you use it, and pay it forward
// This short program interfaces with the Nextion LCD touch display to implement
// a scrollable "text selection dialog". In fact, it's a generic text scroller,
// but can be used as a selection dialog if you wish. Click on any line and it
// flashes - the actual selection code is not implemented here, but basically
// You'd implement a listener on each of the 8 text lines and handle the result
// here on the MC side.
// BUGS:
// OK, there's a problem when the system first starts up, and the error messages
// logged to serial include
// Warning: Could not read update requirement - defaulting to ALL
// Error reading base
// These can safely be ignored, because the system defaults to work without this
// particular part of the code working the first time through. For some reason, reading
// these variables from the Nextion just doesn't work. First time only. However, after
// the first time.. all OK. I would love to know what stuipd thing I have done that is
// causing this :( C'est la vie.
// LIBRARIES...
// For use on Arduino Mirco, do the following...
// Uses the Nextion Library at https://github.com/itead/ITEADLIB_Arduino_Nextion
// 1: see: http://support.iteadstudio.com/support/discussions/topics/11000012238
// --> Delete NexUpload.h and NexUpload.cpp from Nextion library folder to save RAM
// 2. Disable DEBUG_SERIAL_ENABLE in NexConfig.h
// 3. set #define nexSerial Serial1 in NexConfig.h
// If you're using another MC of course you will need to do things suitable for your platform.
#define REFRESH_TOP_LINE 0
#define REFRESH_BOTTOM_LINE 7
#define REFRESH_ALL_LINES 8
#include "Nextion.h" // You may need angle brackets...
#include "NexUpload.h"
#include <SD.h>
#include <SPI.h>
NexUpload nex_download("nex.tft",BUILTIN_SDCARD,115200);
File root;
// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy audio board: pin 10
// Teensy 3.5 & 3.6 on-board: BUILTIN_SDCARD
// Wiz820+SD board: pin 4
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
const int chipSelect = BUILTIN_SDCARD;
// Nextion UI - The file selection dialog - consists of 8 "buttons" showing the menu
// and each of these has a listener so that we know when there's a selection
NexButton t0 = NexButton(2, 1, "f0");
NexButton t1 = NexButton(2, 2, "f1");
NexButton t2 = NexButton(2, 3, "f2");
NexButton t3 = NexButton(2, 4, "f3");
NexButton t4 = NexButton(2, 5, "f4");
NexButton t5 = NexButton(2, 6, "f5");
NexButton t6 = NexButton(2, 9, "f6");
NexButton t7 = NexButton(2, 10, "f7");
NexButton *textLine[] = { &t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7 };
NexVariable baseVar = NexVariable(2, 11, "basex");
NexVariable selectedTrack = NexVariable(2, 8, "va0");
NexSlider trackSlider = NexSlider(2, 15, "h0");
NexVariable requiredUpdate = NexVariable(2, 12, "canUpdate");
NexVariable va1 = NexVariable(2, 19, "va1");
// We "listen" to the slider for the position change of the first line
// and we listen to the text buttons for a selection
NexTouch *nex_listen_list[] = {
&trackSlider,
&t0,
&t1,
&t2,
&t3,
&t4,
&t5,
&t6,
&t7,
NULL
};
// For this demo, the menu items are given as a list of "strings". For a
// file selection dialog, you would want to read filenames from a SD card (for
// example). In that case, you don't want to have them all in memory at the
// same time, so you would implement a "getFileN()" method, and perhaps others
// too - but for seeing how menus can work, this staic array is sufficient.
// Note that on the Arduino, the below is a TERRIBLE way to define strings,
// because they are placed in the very precious RAM. For a demo, this is
// forgiveable :)
char *menuItems[] = {
(char*)"00 There's a black crow ",
(char*)"01 sitting across from",
(char*)"02 me. His wiry legs are",
(char*)"03 crossed. He is dangling",
(char*)"04 my keys, he even fakes",
(char*)"05 a toss. Whatever could",
(char*)"06 it be that has brought",
(char*)"07 me to this loss?",
(char*)"08 On your back with your",
(char*)"09 racks as the stacks are",
(char*)"10 your load. In the back",
(char*)"11 and the racks and the",
(char*)"12 stacks of your load",
(char*)"13 In the back with your",
(char*)"14 racks and you're",
(char*)"15 un-stacking your load.",
(char*)"16 This is not the sound",
(char*)"17 of a new man or crispy",
(char*)"18 realization. It's the",
(char*)"19 sound of the unlocking",
(char*)"20 and the lift away.",
//(char*)"21 Your love will be",
//(char*)"22 Safe with me.",
0
};
uint32_t menuSize;
// The callback "happens" when there is a change in the scroll position of the dialog. This
// means that we need to update one or all of the 8 text lines with new contents. When the up
// or down arrows are pressed, the Nextion automatically does the scrolling up/down for the
// lines that are visible on the screen already, and we only need to update the top (0 for up)
// or the bottom (7 for down) line. However, if the slider was used, we have to update all
// of the lines (8) - so this is somewhat slower in updating. Not too bad though.
void writeMenuStrings(void * = NULL) {
// Ask the Nextion which line(s) require updating. See the REFRESH_ equates at top of file.
uint32_t updateReq;
if (!requiredUpdate.getValue(&updateReq)) {
Serial.println("Warning: Could not read update requirement - defaulting to ALL");
updateReq = REFRESH_ALL_LINES; // do all as a fallback
}
// Get the "base" from the Nextion. This is the index, or starting file # of the first line
// in the selection dialog. As we scroll up, this decreases to 0. As we scroll down, it
// increases to the maximum file # (held in the slider's max value).
uint32_t base;
if (!baseVar.getValue(&base)) {
Serial.println("Error reading base");
base = 0;
}
Serial.print("Base=");
Serial.print(base);
Serial.print(" Update=");
Serial.println(updateReq);
// Based on 'requiredUpdate' from the Nextion we either update only the top line (when up arrow pressed),
// only the bottom line (when down arrow pressed), or we update ALL of the lines (slider dragged). The
// latter is kind of slow, but that doesn't really matter. Could switch the serial speed to 115200 bps to
// make this super-quick, but it works just fine at default 9600 bps.
Serial.println("----------");
switch (updateReq) {
case REFRESH_TOP_LINE:
case REFRESH_BOTTOM_LINE: {
char *p = 0;
if (base + updateReq < menuSize) // strictly speaking, should never be false - can be removed
p = menuItems[base + updateReq];
Serial.println(p);
textLine[updateReq]->setText(p);
}
break;
case REFRESH_ALL_LINES:
default:
for (int i=0; i<8; i++) {
char *p = 0;
if (base + i < menuSize) // strictly speaking, should never be false - can be removed
p = menuItems[base + i];
Serial.println(p);
textLine[i]->setText(p);
}
break;
}
Serial.println("----------");
}
void trackSelectCallback(void *) {
// When a menu item is selected, we read the selected item absolute number from the Nextion
// and use that to lookup the menu string itself, and display both of them on the serial.
uint32_t base;
if (baseVar.getValue(&base)) {
uint32_t selection;
if (selectedTrack.getValue(&selection)) {
Serial.print("#");
Serial.print(selection);
Serial.print(" = ");
Serial.println(menuItems[selection]);
uint32_t val;
if (va1.getValue(&val)){
Serial2.print("t0.txt=");
Serial2.write(0x22);
Serial2.print(menuItems[selection]);
Serial2.write(0x22);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);
}
} else
Serial.println("error retrieving selection");
} else
Serial.println("error retrieving base");
}
// Arduino starts here...
void setup(){
// put your setup code here, to run once:
nex_download.upload();
Serial.begin(9600);
while (!Serial) {}
Serial.println(F("Nextion File Dialog Demo"));
nexInit();
//SD.begin(BUILTIN_SDCARD);
Serial.print("Initializing SD card...");
if (SD.begin(chipSelect)) {
Serial.println("initialization failed!");
//return;
}
Serial.println("initialization done.");
root = SD.open("/");
printDirectory(root, 0);
Serial.println("done!");
//////////////////////////////////////////////////////////////////////////////////////////
// BUG: I have no idea why the delay below is needed, but the communication with Nextion
// fails if it's not there - specifically, the trackSlider.setMaxValue(...) fails. This code
// has generic communication problems with the Nextion but seemingly ONLY ON STARTUP -
// once the scrolling system is going, everything seems hunky dory. So, somewhere there's
// a mistake by yours truly...
delay(1000);
//////////////////////////////////////////////////////////////////////////////////////////
// Attach callbacks - one for the slider, and one each for the selectable lines
trackSlider.attachPop(writeMenuStrings, &trackSlider);
for (int i=0; i<8; i++)
textLine[i]->attachPop(trackSelectCallback, textLine[i]);
// Count the number of menu items and then set the maximum range for the slider
// We subtract 8 from the count because there are 8 lines already visible in the window
menuSize = 0;
while (menuItems[menuSize])
menuSize++;
Serial.print("Menu items: ");
Serial.println(menuSize);
if (!trackSlider.setMaxval(menuSize > 8 ? menuSize - 8 : 0))
Serial.println("Error setting slider maximum!");
writeMenuStrings(); // defaults to REFRESH_ALL_LINES, so screen is populated
}
// Arduino calls this whenever it gets a chance...
void loop() {
nexLoop(nex_listen_list);
}
void printDirectory(File dir, int numTabs) {
while(true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
//Serial.println("**nomorefiles**");
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
//entry.close();
}
}
// EOF
any help would be really appreciated
P.S
the Teensy has lots of space on it so I am using the NexUpload and have fixed a bug in the library that would block the code from running if the SD card was present but no .TFT file on it, now it will load the .TFT file if present or if no .TFT file it will run the normal code without blocking, I am going to try and modify it to delete the .TFT file once it has been loaded to the screen so next time you power it up it doesn't try to load the file again if you haven't removed it, but not got round to it yet yet.
Thanks
Johnathan