Search Code

ESP32-S3 RGB LED மேட்ரிக்ஸ் திட்டம் 3 - மொபைல் போனிலிருந்து உரை

ESP32-S3 RGB LED மேட்ரிக்ஸ் திட்டம் 3 - மொபைல் போனிலிருந்து உரை

திட்டம் 3 – உங்கள் தொலைபேசியிலிருந்து மேட்ரிக்ஸ் உரையைக் கட்டுப்படுத்துதல் (HTTP உரை)

இந்த திட்டத்தில் ESP32-S3 RGB LED மேட்ரிக்ஸ் ஒரு சிறிய வலைப்பக்கத்தை ஹோஸ்ட் செய்கிறது, இதன் மூலம் நீங்கள் ஸ்க்ரோலிங் உரை, நிறம், திசை மற்றும் வேகத்தை உங்கள் தொலைபேசி அல்லது கணினியிலிருந்து நேரடியாக மாற்றலாம். உங்களுக்கு தனி ஆப் தேவையில்லை – வெறும் வலை உலாவி போதும். இது தொகுதியை ஒரு சிறிய Wi-Fi உரை காட்சியாக மாற்றுகிறது, அதை நீங்கள் நிகழ்நேரத்தில் புதுப்பிக்கலாம்.

இந்த தொடரில் உள்ள ஆறு திட்டங்களும் ஒரு YouTube வீடியோவில் விளக்கப்பட்டு நிரூபிக்கப்பட்டுள்ளன. அதே வீடியோ இந்த பக்கத்தில் இணைக்கப்பட்டுள்ளது, எனவே வலை இடைமுகம் எப்படி இருக்கும் மற்றும் உரை மேட்ரிக்ஸில் உடனடியாக எவ்வாறு புதுப்பிக்கப்படுகிறது என்பதை நீங்கள் சரியாகப் பார்க்கலாம். இந்த திட்டத்திற்கான முழு மூலக் குறியீடு கட்டுரைக்கு கீழே தானாக ஏற்றப்படுகிறது, மேலும் குறியீடு பிரிவின் கீழ் பட்டியலிடப்பட்டுள்ள துணை கடைகளிலிருந்து ESP32-S3 RGB LED மேட்ரிக்ஸ் தொகுதியை வாங்கலாம்.

இந்த கட்டுரையில் நெட்வொர்க் தர்க்கம் எவ்வாறு செயல்படுகிறது (வீட்டு Wi-Fi vs அணுகல் புள்ளி) மற்றும் நடத்தையைத் தனிப்பயனாக்க குறியீட்டில் எந்த அமைப்புகளை மாற்றலாம் என்பதில் நாங்கள் கவனம் செலுத்துகிறோம்.

ESP32-S3 RGB LED மேட்ரிக்ஸ் தொகுதி கண்ணோட்டம்

வன்பொருள் இந்த தொடரில் உள்ள மற்ற எல்லா திட்டங்களுக்கும் ஒரே மாதிரியானது: உள்ளமைக்கப்பட்ட 8×8 RGB LED மேட்ரிக்ஸ் மற்றும் பின்புறத்தில் QMI8658C மோஷன் சென்சார் கொண்ட ESP32-S3 மைக்ரோகண்ட்ரோலர் போர்டு. USB-C போர்ட் மின்சாரம் மற்றும் நிரலாக்கத்திற்கு பயன்படுத்தப்படுகிறது, மேலும் விளிம்புகளைச் சுற்றியுள்ள பின்கள் மற்ற IO க்கு இன்னும் கிடைக்கின்றன.:contentReference[oaicite:0]{index=0}

  • ESP32-S3 – Wi-Fi மற்றும் புளூடூத் திறன் கொண்ட மைக்ரோகண்ட்ரோலர்.
  • 8×8 RGB மேட்ரிக்ஸ் – உரை மற்றும் கிராபிக்ஸிற்கான 64 முகவரியிடக்கூடிய RGB LEDகள்.
  • QMI8658C முடுக்கமானி – சாய்வு மற்றும் விளையாட்டு திட்டங்களில் பயன்படுத்தப்படுகிறது.
  • USB போர்ட் – போர்டுக்கு மின்சாரம் வழங்குகிறது மற்றும் Arduino IDE இலிருந்து ஸ்கெட்ச்களை பதிவேற்றுகிறது.
  • வெளிப்படுத்தப்பட்ட பின்கள் – தேவைப்பட்டால் கூடுதல் சென்சார்கள் அல்லது ஆக்சுயேட்டர்களை அனுமதிக்கின்றன.
  • பூட்/ரீசெட் பொத்தான்கள் – ஃபார்ம்வேர் பதிவேற்றம் மற்றும் மறுதொடக்கத்திற்காக.

திட்டம் 3 க்கு, மிக முக்கியமான அம்சம் ESP32 இன் Wi-Fi ஆகும், இது போர்டை உரை கட்டுப்பாட்டு பக்கத்திற்கான ஒரு சிறிய வலை சேவையகமாக செயல்பட அனுமதிக்கிறது.:contentReference[oaicite:1]{index=1}

வீடியோவில் உள்ளடக்கப்பட்ட திட்டங்கள் (நேர முத்திரைகள்)

இந்த தொடருக்கான ஒரு வீடியோ ஆறு திட்டங்களையும் உள்ளடக்கியது. விரைவான குறிப்புக்காக:

  • 00:00 – அறிமுகம்
  • 02:01 – ESP32 போர்டுகளை நிறுவுதல்
  • 03:32 – நூலகங்களை நிறுவுதல்
  • 05:32 – திட்டம் 1: நகரும் புள்ளி
  • 11:11 – திட்டம் 2: உரை ஸ்க்ரோல்
  • 12:59திட்டம் 3: HTTP உரை (இந்த திட்டம்)
  • 16:41 – திட்டம் 4: சாய்வு புள்ளி
  • 18:55 – திட்டம் 5: மேல் அம்பு
  • 20:02 – திட்டம் 6: இலக்கு விளையாட்டு

இந்த கட்டுரையுடன் பணிபுரியும் போது வீடியோவில் HTTP உரை பகுதியைப் பார்க்க நீங்கள் ஊக்குவிக்கப்படுகிறீர்கள். வீடியோ ESP32 ஆல் வலைப்பக்கம் எவ்வாறு உருவாக்கப்படுகிறது மற்றும் உரை, நிறம் மற்றும் வேகத்தை மாற்றுவது LED மேட்ரிக்ஸில் உடனடியாக எவ்வாறு பிரதிபலிக்கிறது என்பதைக் காட்டுகிறது.:contentReference[oaicite:2]{index=2}

Arduino IDE இல் ESP32 போர்டுகளை நிறுவுதல்

நீங்கள் ஏற்கனவே திட்டம் 1 அல்லது 2 ஐ முடித்திருந்தால், போர்டு அமைப்பு முடிந்தது மற்றும் இந்த பகுதியை நீங்கள் தவிர்க்கலாம். இல்லையெனில், Arduino IDE இல் இந்த படிகளைப் பின்பற்றவும்:

  1. File > Preferences ஐத் திறந்து ESP32 போர்டுகள் URL ஐ “Additional Boards Manager URLs” இல் சேர்க்கவும்.
  2. Tools > Board > Boards Manager… க்குச் சென்று, ESP32 ஐத் தேடி, அதிகாரப்பூர்வ ESP32 தொகுப்பை நிறுவவும்.
  3. Tools > Board இலிருந்து சரியான ESP32-S3 RGB மேட்ரிக்ஸ் போர்டைத் தேர்ந்தெடுக்கவும்.
  4. தொகுதியை USB வழியாக இணைத்து Tools > Port இன் கீழ் சரியான சீரியல் போர்ட்டைத் தேர்ந்தெடுக்கவும்.

சரியான ESP32 போர்டு ஆதரவு மற்றும் சரியான போர்ட் இல்லாமல், வலை-சேவையக ஸ்கெட்ச் பதிவேற்றப்படாது.

NeoMatrix மற்றும் தேவையான நூலகங்களை நிறுவுதல்

இந்த திட்டம் முந்தைய உரை ஸ்க்ரோல் திட்டத்தின் அதே நூலகங்களைப் பயன்படுத்துகிறது:

  • Adafruit NeoMatrix
  • Adafruit NeoPixel
  • Adafruit GFX Library

நூலக மேலாளர் வழியாக நிறுவவும்:

  1. Sketch > Include Library > Manage Libraries… ஐத் திறக்கவும்.
  2. Adafruit NeoMatrix ஐத் தேடி Install என்பதைக் கிளிக் செய்யவும்.
  3. சார்புகளின் நிறுவலை ஏற்கவும் (Adafruit GFX மற்றும் Adafruit NeoPixel).

நிறுவப்பட்டதும், File > Examples இன் கீழ் NeoMatrix மற்றும் NeoPixel எடுத்துக்காட்டு ஸ்கெட்ச்களை நீங்கள் காண வேண்டும்.

திட்டம் 3 இல் இரண்டு Wi-Fi முறைகள்

இந்த திட்டத்தில் மிக முக்கியமான கருத்து என்னவென்றால், ESP32 இரண்டு வெவ்வேறு முறைகளில் செயல்பட முடியும்:

  1. ஸ்டேஷன் (STA) முறை – ESP32 உங்கள் இருக்கும் வீட்டு Wi-Fi நெட்வொர்க்குடன் இணைகிறது.
  2. அணுகல் புள்ளி (AP) முறை – வீட்டு Wi-Fi கிடைக்கவில்லை என்றால் ESP32 அதன் சொந்த Wi-Fi நெட்வொர்க்கை உருவாக்குகிறது.

இரண்டு முறைகளும் ஒரே வலை இடைமுகத்தைப் பயன்படுத்துகின்றன: ESP32 இலிருந்தே வழங்கப்படும் ஒரு HTML பக்கம், அங்கு நீங்கள் உரை, நிறம், ஸ்க்ரோல் திசை மற்றும் வேகத்தை மாற்றலாம்.:contentReference[oaicite:3]{index=3}

முறை 1 – வீட்டு Wi-Fi உடன் இணைதல் (ஸ்டேஷன் முறை)

ஸ்டேஷன் முறையில், ESP32 உங்கள் வீடு அல்லது அலுவலக Wi-Fi நெட்வொர்க்கில் இணைகிறது. உங்கள் ரூட்டர் கிடைக்கும்போதெல்லாம் இது விருப்பமான முறையாகும், ஏனெனில்:

  • உங்கள் தொலைபேசி மற்றும் கணினி ஏற்கனவே அதே Wi-Fi நெட்வொர்க்குடன் இணைக்கப்பட்டுள்ளன.
  • ESP32 இன் IP முகவரிக்கு உங்கள் உலாவியை சுட்டிக்காட்டலாம் மற்றும் அந்த நெட்வொர்க்கில் உள்ள எந்த சாதனத்திலிருந்தும் உரையை கட்டுப்படுத்தலாம்.

ஸ்கெட்ச்சின் அமைப்புகள் பிரிவில், உங்கள் Wi-Fi SSID மற்றும் கடவுச்சொல்லை வழங்குகிறீர்கள்:

// வீட்டு Wi-Fi சான்றுகள் (ஸ்டேஷன் முறை) const char* WIFI_SSID = "YourHomeWiFi"; const char* WIFI_PASS = "YourHomePassword";

போர்டு துவங்கிய பிறகு, அது WIFI_SSID உடன் இணைக்க முயற்சிக்கிறது. வெற்றிகரமாக இருந்தால், குறியீடு ஒதுக்கப்பட்ட IP முகவரியை Serial Monitor இல் அச்சிடுகிறது, எடுத்துக்காட்டாக:


Connected to WiFi
IP address: 192.168.1.16

உரையை கட்டுப்படுத்த:

  1. உங்கள் போன் அல்லது PC அதே Wi-Fi நெட்வொர்க்குடன் இணைக்கப்பட்டுள்ளதா என்பதை உறுதிசெய்யவும் (எடுத்துக்காட்டாக, YourHomeWiFi).
  2. ஒரு உலாவியைத் திறந்து, அச்சிடப்பட்ட IP முகவரியை உள்ளிடவும், அதாவது http://192.168.1.16/.
  3. கட்டுப்பாட்டு பக்கம் தோன்றும், இது உரையை தட்டச்சு செய்ய, நிறத்தை தேர்வு செய்ய, திசையை தேர்ந்தெடுக்க, மற்றும் ஸ்க்ரோல் வேகத்தை சரிசெய்ய உங்களை அனுமதிக்கிறது.

முறை 2 – தனித்த அணுகல் புள்ளி (AP முறை)

ESP32 உங்கள் வீட்டு Wi-Fi உடன் இணைக்க முடியாவிட்டால் (தவறான கடவுச்சொல், நெட்வொர்க் கிடைக்கவில்லை, அல்லது நீங்கள் தொகுதியை வெளியே பயன்படுத்துகிறீர்கள்), ஸ்கெட்ச் தானாகவே அணுகல் புள்ளி முறைக்கு மாறுகிறது. AP முறையில், ESP32 தானே அதன் சொந்த நெட்வொர்க் பெயர் மற்றும் கடவுச்சொல்லுடன் ஒரு Wi-Fi ஹாட்ஸ்பாட்டாக மாறுகிறது.

இந்த திட்டத்தில், AP அமைப்புகள் பின்வருமாறு நிலையானவை:


// Access Point (AP) credentials (fallback mode)
const char* AP_SSID = "ESP32";
const char* AP_PASS = "password";

ஸ்டேஷன் முறை தோல்வியடையும் போது, தொகுதி AP முறைக்கு மாறி, ESP32 என்று அழைக்கப்படும் ஒரு Wi-Fi நெட்வொர்க்கை ஒளிபரப்பத் தொடங்குகிறது. மேட்ரிக்ஸை கட்டுப்படுத்த:

  1. உங்கள் போன் அல்லது கணினியில், Wi-Fi அமைப்புகளைத் திறந்து, ESP32 நெட்வொர்க்குடன் இணைக்கவும்.
  2. கடவுச்சொல்லை உள்ளிடவும் password (குறியீட்டில் வரையறுக்கப்பட்டுள்ளபடி).
  3. இணைந்த பிறகு, ஒரு உலாவியைத் திறந்து http://192.168.4.1/ க்கு செல்லவும் (ESP32 AP முறைக்கான இயல்புநிலை IP).
  4. அதே கட்டுப்பாட்டு பக்கம் தோன்றும், இது உரை, நிறம், வேகம், மற்றும் திசையை மாற்ற உங்களை அனுமதிக்கிறது.

இந்த தோல்வி-பாதுகாப்பு நடத்தை திட்டத்தை எங்கும் பயனுள்ளதாக்குகிறது: வீட்டில், ஆய்வகத்தில், அல்லது ரூட்டர் கிடைக்காத ஒரு டெமோ சூழலில்.

திட்டம் 3 – குறியீட்டில் முக்கிய அமைப்புகள்

முழு HTTP Text ஸ்கெட்ச் இந்த கட்டுரைக்கு கீழே இணையதளத்தால் ஏற்றப்படுகிறது. இங்கே நீங்கள் திருத்த வாய்ப்புள்ள மிக முக்கியமான உள்ளமைவு விருப்பங்களை மட்டுமே நாங்கள் ஆவணப்படுத்துகிறோம்.

Wi-Fi மற்றும் அணுகல் புள்ளி அமைப்புகள்

ஸ்கெட்ச்சின் மேலே Wi-Fi உள்ளமைவு பகுதியைக் காண்பீர்கள். ஸ்டேஷன் (வீட்டு Wi-Fi) சான்றுகளை மட்டும் மாற்றவும்; AP அமைப்புகள் பொதுவாக இயல்புநிலையாக வைக்கப்படுகின்றன:


// ---------- Wi-Fi SETTINGS ----------

// Home Wi-Fi (Station mode)
const char* WIFI_SSID = "YourHomeWiFi";      // put your router SSID here
const char* WIFI_PASS = "YourHomePassword";  // put your router password here

// Fallback Access Point (AP mode)
const char* AP_SSID = "ESP32";               // fixed AP name
const char* AP_PASS = "password";            // fixed AP password

நடத்தை:

  • WIFI_SSID மற்றும் WIFI_PASS சரியாக இருந்து நெட்வொர்க் கிடைத்தால் → ESP32 ஒரு சாதாரண Wi-Fi சாதனமாக இணைகிறது (ஸ்டேஷன் முறை).
  • இணைப்பு ஒரு காலக்கெடுவிற்குப் பிறகு தோல்வியடைந்தால் → ESP32 AP_SSID மற்றும் AP_PASS ஐப் பயன்படுத்தி அதன் சொந்த AP ஐத் தொடங்குகிறது.

மேட்ரிக்ஸ் பின், அளவு, மற்றும் பிரகாசம்

இந்த அமைப்புகள் முந்தைய திட்டங்களைப் போலவே உள்ளன:


// Matrix configuration
const int MATRIX_PIN    = 14;   // RGB matrix data pin
const int MATRIX_WIDTH  = 8;
const int MATRIX_HEIGHT = 8;

// Overall display brightness (0–255)
uint8_t matrixBrightness = 40;  // adjust for your environment

இந்த போர்டுக்கு MATRIX_PIN14 இல் வைக்கவும். அதிக ஒளி தேவைப்பட்டால் matrixBrightness ஐ அதிகரிக்கலாம், ஆனால் குறைந்த மதிப்புகள் நெருக்கமான பார்வைக்கு மிகவும் வசதியானவை.

இயல்புநிலை உரை மற்றும் ஸ்க்ரோல் அமைப்புகள்

போர்டு துவங்கும்போது, நீங்கள் வலைப்பக்கத்தைத் திறந்து புதிய ஒன்றை தட்டச்சு செய்யும் வரை அது ஒரு ஆரம்ப செய்தியைக் காட்டுகிறது. உள்ளமைவில் இயல்புநிலை உரையை மாற்றலாம்:


// Default message shown at startup
String currentText = "Robojax";   // overwrite from web UI later

மீதமுள்ள ஸ்க்ரோல் நடத்தை வலை இடைமுகத்தால் புதுப்பிக்கப்படும் மாறிகளின் தொகுப்பால் கட்டுப்படுத்தப்படுகிறது:


// Scroll delay in milliseconds (lower = faster)
int scrollDelayMs = 50;

// Scroll direction: 0=left, 1=right, 2=up, 3=down
int scrollDirection = 0;   // default: scroll left

வலைப்பக்கம் ஸ்லைடர் மற்றும் பொத்தான் தேர்வுகளின் அடிப்படையில் புதிய மதிப்புகளை அனுப்புகிறது. Arduino பக்கத்திலிருந்து, நீங்கள் தெரிந்து கொள்ள வேண்டியது:

  • scrollDelayMs ஐ குறைப்பது உரையை வேகமாக நகர்த்துகிறது.
  • scrollDelayMs ஐ அதிகரிப்பது அதை மெதுவாக நகர்த்துகிறது.
  • scrollDirection ஐ மாற்றுவது இடது, வலது, மேல், அல்லது கீழ் ஸ்க்ரோல் முறைகளுக்கு இடையில் மாறுகிறது.

உரை நிறம் (வலைப்பக்கத்திலிருந்து கட்டுப்படுத்தப்படுகிறது)

உரையின் நிறம் மூன்று 0–255 மதிப்புகளால் (சிவப்பு, பச்சை, நீலம்) கட்டுப்படுத்தப்படுகிறது. வலைப்பக்கத்தில் புதிய நிறத்தை தேர்வு செய்யும்போது அவை புதுப்பிக்கப்படுகின்றன:


// Current text color (R, G, B)
uint8_t textRed   = 255;
uint8_t textGreen = 255;
uint8_t textBlue  = 255;

உலாவியில் ஒரு நிறத்தை தேர்வு செய்து Apply என்பதை கிளிக் செய்யும்போது, ESP32 RGB மதிப்புகளை பாகுபடுத்தி இந்த மூன்று மாறிகளை புதுப்பிக்கிறது; உரை உடனடியாக மேட்ரிக்ஸில் நிறத்தை மாற்றுகிறது. வீடியோவில், இந்த நடத்தை பல நிற மாற்றங்களுடன் நிரூபிக்கப்படுகிறது, சிவப்பு, பச்சை மற்றும் நீல எடுத்துக்காட்டுகள் உட்பட.

சுருக்கம்

திட்டம் 3 உங்கள் ESP32-S3 RGB LED மேட்ரிக்ஸை முழுமையாக வயர்லெஸ் உரை காட்சியாக மாற்றுகிறது, இதை நீங்கள் வலை உலாவி கொண்ட எந்த சாதனத்திலும் கட்டுப்படுத்தலாம். ஸ்கெட்ச் வலுவாக இருக்க வடிவமைக்கப்பட்டுள்ளது:

  • இது முதலில் நீங்கள் கட்டமைத்த SSID மற்றும் கடவுச்சொல்லைப் பயன்படுத்தி உங்கள் வீட்டு Wi-Fi உடன் இணைக்க முயற்சிக்கிறது.
  • அது தோல்வியுற்றால், அது தானாகவே ESP32 என்ற பெயர் மற்றும் password என்ற கடவுச்சொல்லுடன் ஒரு அணுகல் புள்ளியாக மாறும்.
  • இரண்டு முறைகளிலும், உலாவியில் சரியான IP முகவரியைத் திறப்பது உரை, நிறம், திசை மற்றும் வேகத்திற்கான அதே கட்டுப்பாட்டுப் பக்கத்தைக் காட்டுகிறது.

முழுமையான HTTP Text குறியீடு இந்தக் கட்டுரைக்குக் கீழே கிடைக்கிறது (இணையதளத்தில் தானாக ஏற்றப்படுகிறது). முழுமையான படிப்படியான விளக்கத்திற்கும், உரை நிகழ்நேரத்தில் எவ்வாறு புதுப்பிக்கப்படுகிறது என்பதற்கான நேரடி ஆர்ப்பாட்டத்திற்கும், வீடியோவின் Project 3 பகுதியைப் பார்க்க மறக்காதீர்கள். நீங்களே இந்தத் திட்டத்தை உருவாக்க விரும்பினால், குறியீட்டின் கீழ் பட்டியலிடப்பட்டுள்ள இணைப்பு இணைப்புகளைப் பயன்படுத்தி ESP32-S3 RGB LED Matrix தொகுதியையும் வாங்கலாம்.

படங்கள்

ESP32 S3 Matrix
ESP32 S3 Matrix
ESP32 S3 Matrix  pin out
ESP32 S3 Matrix pin out
ESP32-S3_RGB_8x8_matrix-3
ESP32-S3_RGB_8x8_matrix-3
ESP32 S3 Matrix displaying rainbow heart
ESP32 S3 Matrix displaying rainbow heart
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3 RGB Matrix- Mobile Phone Text
ESP32-S3 RGB Matrix- Mobile Phone Text
801-ESP32-S3 RGB LED Matrix Project 3 - Text from mobile phone
மொழி: C++
/*
  Project 4: HTTP Text Scroll – ESP32-S3 RGB LED Matrix (Waveshare)

  - Connects to your home WiFi (station mode, with AP fallback).
  - Serves a web page where you can set:
      * Text
      * Color
      * Display ON/OFF
      * Scroll direction (Left / Right / Up / Down)
      * Scroll delay (speed)
  - Supports 8×8 RGB LED matrix using Adafruit_NeoMatrix.

  ▶️ Video Tutorial:
  https://youtu.be/JKLuYrRcLMI

  📄 Resources & Code Page:
  https://robojax.com/your-resources-page-here

  HTTP_Text_Scroll
*/

#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

// ======================= WIFI SETTINGS =========================
// Home WiFi (change these to your router credentials)
const char* WIFI_SSID = "Biseem";
const char* WIFI_PASS = "wan9&Jang~";

// Fallback Access Point
const char* AP_SSID = "ESP32";
const char* AP_PASS = "password";

// ======================= MATRIX SETTINGS =======================

#define MATRIX_PIN    14
#define MATRIX_WIDTH  8
#define MATRIX_HEIGHT 8

// 0, 1, 2, or 3 – adjust if text orientation is wrong with USB up
#define MATRIX_ROTATION 0
#define BRIGHTNESS 15

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
  MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN,
  NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
  NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
  NEO_RGB + NEO_KHZ800
);

// ======================= SCROLL STATE ==========================

enum ScrollDir {
  DIR_LEFT = 0,
  DIR_RIGHT,
  DIR_UP,
  DIR_DOWN
};

String   scrollText  = "Robojax";
uint16_t textColor   = 0xFFFF;  // default white
bool     displayOn   = true;
ScrollDir currentDir = DIR_LEFT;

// 1 step every this many ms (lower = faster)
unsigned long scrollInterval = 80;
unsigned long lastScrollTime = 0;

// Horizontal scroll position
int scrollX = MATRIX_WIDTH;
int scrollY = 0;              // top row

// State for vertical per-letter scroll
int vertCharIndex = 0;        // which character of the string
int vertY         = MATRIX_HEIGHT;    // vertical position of that character

// ======================= WEB SERVER ============================

WebServer server(80);

// ======================= HTML PAGE ============================

const char MAIN_page[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ESP32 Text Scroll</title>
<style>
  body {
    font-family: Arial, sans-serif;
    background: #111;
    color: #eee;
    text-align: center;
    margin: 0;
    padding: 10px;
  }
  .container {
    max-width: 360px;
    width: 100%%;
    margin: 0 auto;
    background: #222;
    padding: 12px;
    border-radius: 10px;
    box-sizing: border-box;
  }
  input[type="text"] {
    width: 100%%;
    padding: 8px;
    box-sizing: border-box;
    border-radius: 5px;
    border: 1px solid #444;
    background: #111;
    color: #eee;
    margin-bottom: 10px;
  }
  .row {
    margin: 10px 0;
  }
  .label {
    display: block;
    margin-bottom: 5px;
    text-align: left;
  }
  .toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
  }
  .arrow-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: repeat(3, 50px);
    gap: 8px;
    justify-content: center;
    margin-top: 10px;
  }
  .arrow-btn {
    background: #333;
    border: 1px solid #555;
    color: #eee;
    font-size: 18px;
    border-radius: 10px;
    cursor: pointer;
    width: 100%%;
    height: 100%%;
  }
  .arrow-btn.active {
    background: #0a84ff;
  }
  .arrow-btn:disabled {
    opacity: 0.5;
    cursor: default;
  }
  button#applyBtn {
    margin-top: 15px;
    padding: 10px 20px;
    border-radius: 8px;
    border: none;
    background: #0a84ff;
    color: #fff;
    font-size: 16px;
    cursor: pointer;
  }
  button#applyBtn:active {
    transform: scale(0.97);
  }
</style>
</head>
<body>
  <div class="container">
    <h2>Robojax ESP32-S3 Matrix Text Scroll</h2>

    <div class="row">
      <span class="label">Text to scroll:</span>
      <input type="text" id="text" value="Hello" />
    </div>

    <div class="row">
      <span class="label">Color:</span>
      <input type="color" id="color" value="#ffffff" />
    </div>

    <div class="row">
      <span class="label">Scroll Delay (fast → slow):</span>
      <input
        type="range"
        id="speed"
        min="20"
        max="300"
        value="80"
        oninput="document.getElementById('speedVal').innerText = this.value + ' ms';"
      />
      <div id="speedVal" style="text-align:right;font-size:12px;margin-top:4px;">
        80 ms
      </div>
    </div>

    <div class="row">
      <label class="toggle">
        <input type="checkbox" id="power" checked />
        <span>Display ON</span>
      </label>
    </div>

    <div class="row">
      <span class="label">Scroll Direction:</span>
      <div class="arrow-grid">
        <div></div>
        <button class="arrow-btn" id="btnUp" onclick="setDir('up')">&#9650;</button>
        <div></div>

        <button class="arrow-btn" id="btnLeft" onclick="setDir('left')">&#9664;</button>
        <div></div>
        <button class="arrow-btn" id="btnRight" onclick="setDir('right')">&#9654;</button>

        <div></div>
        <button class="arrow-btn" id="btnDown" onclick="setDir('down')">&#9660;</button>
        <div></div>
      </div>
    </div>

    <button id="applyBtn" onclick="sendUpdate()">Apply</button>
    <p id="status"></p>
  </div>

<script>
  let currentDir = 'left';

  function setDir(dir) {
    currentDir = dir;
    document.querySelectorAll('.arrow-btn').forEach(b => b.classList.remove('active'));
    if (dir === 'up')    document.getElementById('btnUp').classList.add('active');
    if (dir === 'down')  document.getElementById('btnDown').classList.add('active');
    if (dir === 'left')  document.getElementById('btnLeft').classList.add('active');
    if (dir === 'right') document.getElementById('btnRight').classList.add('active');
    sendUpdate();
  }

  function sendUpdate() {
    const text  = document.getElementById('text').value;
    const color = document.getElementById('color').value;
    const power = document.getElementById('power').checked ? '1' : '0';
    const speed = document.getElementById('speed').value;

    const url = `/update?text=${encodeURIComponent(text)}&color=${encodeURIComponent(color)}&power=${power}&dir=${currentDir}&speed=${speed}`;

    fetch(url)
      .then(r => r.text())
      .then(t => {
        document.getElementById('status').innerText = t;
      })
      .catch(err => {
        document.getElementById('status').innerText = 'Error sending update';
      });
  }

  // Set default active
  setDir('left');
</script>
</body>
</html>
)rawliteral";

// ======================= HELPERS ===============================

bool isHexChar(char c) {
  return (c >= '0' && c <= '9') ||
         (c >= 'a' && c <= 'f') ||
         (c >= 'A' && c <= 'F');
}

String urlDecode(const String &src) {
  String result;
  result.reserve(src.length());
  for (size_t i = 0; i < src.length(); i++) {
    char c = src[i];
    if (c == '+') {
      result += ' ';
    } else if (c == '%' && i + 2 < src.length()) {
      char h1 = src[i + 1];
      char h2 = src[i + 2];
      if (isHexChar(h1) && isHexChar(h2)) {
        char hex[3] = {h1, h2, 0};
        int val = (int)strtol(hex, nullptr, 16);
        result += (char)val;
        i += 2;
      } else {
        result += c;
      }
    } else {
      result += c;
    }
  }
  return result;
}

uint16_t colorFromHex(const String &hex) {
  // Expect "#RRGGBB" or "RRGGBB"
  String c = hex;
  if (c.startsWith("#")) c.remove(0, 1);
  if (c.length() != 6) {
    // default white
    return matrix.Color(255, 255, 255);
  }
  long value = strtol(c.c_str(), NULL, 16);
  uint8_t r = (value >> 16) & 0xFF;
  uint8_t g = (value >> 8) & 0xFF;
  uint8_t b = (value) & 0xFF;
  return matrix.Color(r, g, b);
}

void resetScrollPosition() {
  int textWidth  = scrollText.length() * 6;  // default font ~6 px per char
  int textHeight = 8;                        // 5x7 font fits in 8

  switch (currentDir) {
    case DIR_LEFT:
      // Start from just outside the right edge
      scrollX = MATRIX_WIDTH;
      scrollY = 0;
      break;

    case DIR_RIGHT:
      // Start from just outside the left edge
      scrollX = -textWidth;
      scrollY = 0;
      break;

    case DIR_UP:
      // Per-letter vertical scroll, starting with first character below matrix
      vertCharIndex = 0;
      vertY = MATRIX_HEIGHT;   // 8 → enters from bottom
      break;

    case DIR_DOWN:
      // Per-letter vertical scroll, starting with first character above matrix
      vertCharIndex = 0;
      vertY = -textHeight;     // -8 → enters from top
      break;
  }
}

// ======================= HTTP HANDLERS =========================

void handleRoot() {
  server.send_P(200, "text/html", MAIN_page);
}

void handleUpdate() {
  if (server.hasArg("text")) {
    String txt = urlDecode(server.arg("text"));
    if (txt.length() == 0) {
      scrollText = " ";
    } else {
      scrollText = txt;
    }
  }

  if (server.hasArg("color")) {
    String hex = server.arg("color");
    textColor = colorFromHex(hex);
  }

  if (server.hasArg("power")) {
    String p = server.arg("power");
    displayOn = (p == "1");
  }

  if (server.hasArg("dir")) {
    String d = server.arg("dir");
    if (d == "left")      currentDir = DIR_LEFT;
    else if (d == "right") currentDir = DIR_RIGHT;
    else if (d == "up")    currentDir = DIR_UP;
    else if (d == "down")  currentDir = DIR_DOWN;
  }

  if (server.hasArg("speed")) {
    String s = server.arg("speed");
    int val = s.toInt();

    // simple safety clamp
    if (val < 10)   val = 10;    // very fast
    if (val > 1000) val = 1000;  // 1 second max

    scrollInterval = (unsigned long)val;
    // Serial.print("Scroll interval set to ");
    // Serial.print(scrollInterval);
    // Serial.println(" ms");
  }

  resetScrollPosition();
  server.send(200, "text/plain", "Updated");
}

// ======================= SCROLL LOGIC ==========================

void drawScroll() {
  if (!displayOn) {
    matrix.fillScreen(0);
    matrix.show();
    return;
  }

  int textWidth  = scrollText.length() * 6;
  int textHeight = 8;

  matrix.fillScreen(0);
  matrix.setTextSize(1);
  matrix.setTextWrap(false);
  matrix.setTextColor(textColor);

  // -------- HORIZONTAL SCROLL (LEFT / RIGHT) --------
  if (currentDir == DIR_LEFT || currentDir == DIR_RIGHT) {
    matrix.setCursor(scrollX, 0);
    matrix.print(scrollText);
    matrix.show();

    if (currentDir == DIR_LEFT) {
      scrollX--;
      if (scrollX < -textWidth) {
        scrollX = MATRIX_WIDTH;
      }
    } else { // DIR_RIGHT
      scrollX++;
      if (scrollX > MATRIX_WIDTH) {
        scrollX = -textWidth;
      }
    }
    return;
  }

  // -------- VERTICAL SCROLL (UP / DOWN) – PER LETTER --------

  if (scrollText.length() == 0) {
    matrix.show();
    return;
  }

  // Current character
  char c = scrollText[vertCharIndex];

  int charWidth  = 6;
  int baseX = (MATRIX_WIDTH - charWidth) / 2;  // center horizontally

  matrix.setCursor(baseX, vertY);
  matrix.print(c);
  matrix.show();

  if (currentDir == DIR_UP) {
    // Move character upwards
    vertY--;
    if (vertY < -textHeight) {
      // This character is fully passed, go to next
      vertY = MATRIX_HEIGHT;
      vertCharIndex++;
      if (vertCharIndex >= scrollText.length()) {
        vertCharIndex = 0; // loop back to first character
      }
    }
  } else if (currentDir == DIR_DOWN) {
    // Move character downwards
    vertY++;
    if (vertY > MATRIX_HEIGHT) {
      // This character is fully passed, go to next
      vertY = -textHeight;
      vertCharIndex++;
      if (vertCharIndex >= scrollText.length()) {
        vertCharIndex = 0; // loop back
      }
    }
  }
}

// ======================= WIFI INIT =============================

void startAPFallback() {
  Serial.println("Starting AP fallback...");
  WiFi.mode(WIFI_AP);
  bool apOk = WiFi.softAP(AP_SSID, AP_PASS);
  if (apOk) {
    Serial.print("AP started. SSID: ");
    Serial.print(AP_SSID);
    Serial.print("  IP: ");
    Serial.println(WiFi.softAPIP());
  } else {
    Serial.println("Failed to start AP.");
  }
}

void connectWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  Serial.print("Connecting to WiFi ");
  Serial.print(WIFI_SSID);

  unsigned long startAttempt = millis();
  const unsigned long timeout = 10000; // 10s

  while (WiFi.status() != WL_CONNECTED && (millis() - startAttempt) < timeout) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();

  if (WiFi.status() == WL_CONNECTED) {
    Serial.print("Connected. IP address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("WiFi connect failed, starting AP fallback.");
    startAPFallback();
  }
}

// ======================= SETUP & LOOP ==========================

void setup() {
  Serial.begin(115200);
  delay(500);

  // Matrix init
  matrix.begin();
  matrix.setRotation(MATRIX_ROTATION);
  matrix.setBrightness(BRIGHTNESS);
  matrix.fillScreen(0);
  matrix.show();

  // WiFi
  connectWiFi();

  // Web server routes
  server.on("/", handleRoot);
  server.on("/update", handleUpdate);
  server.onNotFound([]() {
    server.send(404, "text/plain", "Not found");
  });
  server.begin();
  Serial.println("HTTP server started.");

  resetScrollPosition();
}

void loop() {
  server.handleClient();

  unsigned long now = millis();
  if (now - lastScrollTime >= scrollInterval) {
    lastScrollTime = now;
    drawScroll();
  }
}

நீங்கள் தேவைப்படும் எண்ணங்கள்

வளங்கள் மற்றும் மேற்கோள்கள்

கோப்புகள்📁

பிரிட்சிங் கோப்பு