My take on the ‘Obsolete’ YouTube Subscriber Counter!

//My take on the ‘Obsolete’ YouTube Subscriber Counter!
TUTORIAL


The Most Amazing YouTube Subscriber Counter!

-=Ok… probably not…=-

HELP OUT

All my content is free.

If you feel that my videos are helping and you would like to contribute, you can toss some coins in the Tip Jar via PayPal.

Select amount then click the “Donate” button.

Brainy-Bits Tip Jar Amount
OVERVIEW

Tadahh!!!

Well ok, it’s really nothing that special, but it’s my take on the YouTube subscribers counter!

Since Google crippled the YouTube API recently, see my last video for more info on that….

I had to add some other things to make it still relevant and somewhat useful.

So here’s what I came up with…

WHAT CAN IT DO?

Like I said before, since the YouTube API doesn’t update the Subscribers count until you reach a certain amount, depending on how many you have already, see this chart:

So just having a counter that counts the Subscribers would be pretty useless…

After thinking about it I decided to add these functions to make my YouTube counter more relevant:

  • YouTube Subscribers
  • YouTube Total Views
  • Clock
  • Quote of the Day

So now having this on the wall in my workshop makes a little more sense…

THE HARDWARE USED

I decided to go traditional for the number display, I’m using 8x Max7219 LED matrix, these are easy to find and are inexpensive.

But I wanted to add some sort of display to show what those numbers meant.

I decided to use a 2.8 inches Nextion LCD screen, like the Max7219 it’s inexpensive and easy to find.

And of course the NodeMCU Version 2 to get everything working.

THE PLAN

So what I decided to do with all this stuff is this:

The YouTube Information:

  • Number of Subscribers

  • Number of Total views

Small animations on the Nextion LCD to describe what the numbers shown on the LED matrix mean:

The Clock:

  • Well it’s a clock….

Small animation of Homer falling with clocks on the Nextion LCD 🙂

The Quote of the Day:

  • Picks a quote from a list to show at random

Again another Homer animation, this time with glasses and talking 🙂

MAKING SIMPLE ANIMATION ON NEXTION LCD

The 2.8 inch Nextion I’m using for this project only has 4 megabytes of memory available, so I couldn’t make those animation very long without maxing out the memory available.

Also, the ‘basic’ cheap Nextion LCD like I’m using, don’t support video files (only the more expensive ones do that, 80+$) so the animation are made by uploading separate pictures, kinda like an animated GIF.

You might think that since the Nextion I’m using has a resolution of 320×240 pixels, you could upload a lot of pictures, but that’s not the case 🙁

The Nextion Editor converts the images you upload to 16 bits, with no way to change it, so those small 6Kb pictures become 150Kb each!!!!!

So I ended up using 6 frames/pictures for the Clock/Homer animation, and 5 for the YouTube subs and views.

Here’s how to create those animation on the Nextion:

https://www.itead.cc/blog/advanced-application-1-use-timer-variable-and-if-to-implement-gif-animation

PUTTING IT ALL TOGETHER

To make a case for the MAX7219 LED matrix and the Nextion I used my newly acquired Sindoh 3D Printer.

I wanted to have at least eight Max7219 LED matrix to have enough space for the number area.

I found this great 3D modular case model on Thingiverse:

https://www.thingiverse.com/thing:2811071

It’s one of the best one out there for the Max7219 modules sI’m using in this project.

The fact that it’s modular, enables you to make it as big as you want.

For the Nextion 2.8″ LCD screen, again I found this case on Thingiverse:

https://www.thingiverse.com/thing:3394432

It’s big enough to house the LCD and the NodeMCU.

The MAX7219 modules are attached together using some jumpers.

I’m using a regular 5V external power supply (1 Amp) plugged into the NodeMCU to power everything.

I’m using the 3.3v output from the NodeMCU to power the LED Matrix.

From my testing, those 8x LED matrix only draw around 50mA when displaying some numbers or text.

To power the Nextion LCD, I’m using the VIN pin on the NodeMCU, which can be used to power the NodeMCU if you want, but it can also output regulated 5V, which the Nextion needs!

The Nextion 2.8 inch LCD screen draws around 50mA.

So that’s 100mA total for the LED matrix and the Nextion screen.

The Regulator on the NodeMCU can provide up to 800mA, so we’re good there!

CONNECTION DIAGRAM

The connections are pretty easy:

We are powering the LED Matrix using the 3.3V and GND from the NodeMCU

For the Nextion LCD, which requires 5V, we are again using the NodeMCU, the VIN pin on the NodeMCU can be used as a power input to power it without using the USB plug, but can also output 5V.  So the VIN and GND are used to power the Nextion LCD.

The TX and RX pin of the NodeMCU are connected to the RX and TX pins of the Nextion.

Pins D5, D7 and D8 of the NodeMCU are connected to the right side of the Matrix using CLK, DIN and CS.

THE CODE

This code uses a ‘lot’ of libraries:

  • 2 for the YouTube API
  • another for the clock (NTP server)
  • 2 libraries for the LED Matrix
  • one for the Nextion LCD
  • and 3 more for wifi and stuff

You can find links to all those at the bottom of this page.

The trickiest part of this code, funny enough, was to find a way to insert some commas in the numbers to make them more readable on the LED Matrix.

/* YouTube Counter LED Display

Created by Yvan / https://Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!

*/

#include "Nextion.h"  // https://github.com/jyberg/Enhanced-Nextion-Library

#include <MD_Parola.h>   // Library to control LED Matrix  https://github.com/MajicDesigns/MD_Parola
#include <MD_MAX72xx.h>  // Library needed for MD_Parola   https://github.com/MajicDesigns/MD_MAX72xx
#include <SPI.h>

#include <YoutubeApi.h>  // created by Brian Lough https://github.com/witnessmenow/arduino-youtube-api
#include <ArduinoJson.h> // *Version 5.13.5 needed* - created by bblanchon https://github.com/bblanchon/ArduinoJson

#include <ESP8266WiFi.h> // Library for WiFi communication (installed by default with NodeMCU board)

#include <NTPClient.h>  // https://github.com/arduino-libraries/NTPClient
#include <WiFiUdp.h>

NexPage page0 = NexPage(0, 0, "page0");
NexPage page1 = NexPage(1, 0, "page1");
NexPage page2 = NexPage(2, 0, "page2");
NexPage page3 = NexPage(3, 0, "page3");

// List of Quotes
const char q1[] = "A conscience is what hurts when all your other parts feel so good.";
const char q2[] = "Think Im Sarcastic? Watch Me Pretend To Care!";
const char q3[] = "A conclusion is the part where you got tired of thinking.";
const char q4[] = "Two wrongs do not make a right, take your parents as an example.";
const char q5[] = "Accept that some days you are the pigeon, and some days you are the statue.";
const char q6[] = "Always remember that you are absolutely unique... Just like everyone else...";
const char q7[] = "As the Joker said, if you are good at something why do it for free...";
const char q8[] = "Avoid arguments about the toilet seat...use the sink...";
const char q9[] = "I like you. You remind me of when I was young and stupid.";
const char q10[]= "Congratulations, If you press the elevator button three times it goes into hurry mode – really...";
const char q11[]= "Do not take life too seriously, you will not get out alive.";
const char q12[]= "Honesty is the best policy but insanity is the best defense.";
const char q13[]= "I did not climb to the top of the food chain to be a vegetarian...";
const char q14[]= "If a stranger offers you a piece of candy...take two...";
const char q15[]= "I did not say it was your fault, I said I was blaming you.";
const char q16[]= "If I promise to miss you, will you go away?";
const char q17[]= "I am smiling. This should scare you.";
const char q18[]= "It takes patience to listen.. it takes skill to pretend you are listening.";
const char q19[]= "Never tell your problems to anyone...20% do not care and the other 80% are glad you have them...";
const char q20[]= "Oh... I did not tell you? Then It must be none of your business...";
const char q21[]= "Oh... Sorry... Did you mistake me for someone who cares?";
const char q22[]= "Remember, everyone seems normal until you get to know them...";
const char q23[]= "Suicide: Mans way of telling God - You can not fire me, I quit!";
const char q24[]= "The grass may be greener on the other side but at least you do not have to mow it.";
const char q25[]= "We are born naked, wet and hungry. Then things get worse.";

const char *quote_list[] = { 
 q1, q2, q3, q4, q5, q6, q7, q8, q9, q10,
 q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24 };
 
int chosen_quote;
char current_quote[100];  // temp storage for fortune


// Define NTP Client to get time
const long utcOffsetInSeconds = -14400;
char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);


#define HARDWARE_TYPE MD_MAX72XX::FC16_HW

/*  PAROLA_HW,    ///< Use the Parola style hardware modules.
    GENERIC_HW,   ///< Use 'generic' style hardware modules commonly available.
    ICSTATION_HW, ///< Use ICStation style hardware module.
    FC16_HW       ///< Use FC-16 style hardware module.
*/

#define MAX_DEVICES 8  // Number of modules connected
#define CLK_PIN   D5   // CLK pin of matrix connected to pin D5 on NodeMCU
#define DATA_PIN  D7   // DATA pin of matrix connected to pin D7 on NodeMCU
#define CS_PIN    D8   // CS pin of matrix connected to pin D8 on NodeMCU

MD_Parola MATRIX = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);  // Create instance of MD_Parola named MATRIX

#define wifi_name "xxxxx"     // your network SSID (name)
#define wifi_password "xxxxx"  // your network key
#define google_api_key "xxxxx"  // your google API Key
#define youtube_channel_id "xxxxx" // your YouTube Channel ID

WiFiClientSecure client;  // create instance of WiFi named client

YoutubeApi get_from_youtube(google_api_key, client);  // Create instance of YoutubeAPI named get_from_youtube

long subs = 0;  // Variable to save number of Subscribers YouTube 
long total_views = 0;  // Variable to save number of total views on YouTube



void quotes() {

  uint8_t scrollSpeed = 35;    // default frame delay value
  textEffect_t scrollEffect = PA_SCROLL_LEFT;
  textPosition_t scrollAlign = PA_LEFT;
  uint16_t scrollPause = 0; // in milliseconds

  MATRIX.setTextEffect(scrollEffect, scrollEffect);
  MATRIX.displayClear();
  MATRIX.displayReset();
  
  for (int x=0; x<2; x++) {   // Display quote of the day twice
    MATRIX.displayText(current_quote, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);   
    while (!MATRIX.displayAnimate()) {    // If finished displaying message
      yield();
    }
  }
}



void getsubs() {

  char buf[21];
  char thousand[21];
  char million[21];
  get_from_youtube.getChannelStatistics(youtube_channel_id);
  subs=get_from_youtube.channelStats.subscriberCount;
 
  if (subs>=1000000){
     snprintf(thousand,sizeof(thousand),"%ld,%03ld",subs/1000, subs%1000);
     thousand[0] = ',';
     if (subs>=10000000){
       thousand[1] = 0x20;
     }
     snprintf(million,sizeof(million),"%ld",subs/1000000);
     strcpy(buf, million);
     strcat(buf, thousand);
   }

   if ((subs>=1000) && (subs<1000000)) {
     snprintf(buf,sizeof(buf),"%ld,%03ld",subs/1000, subs%1000);
   }
   
   if (subs<1000)  {
     snprintf(buf,sizeof(buf),"%ld",subs); 
     }
    MATRIX.print(buf);
    delay(10000);
}


void gettotalviews() {

  char buf[21];
  char thousand[21];
  char million[21];

  get_from_youtube.getChannelStatistics(youtube_channel_id);
  total_views=get_from_youtube.channelStats.viewCount;
 
  if (total_views>=1000000){
     snprintf(thousand,sizeof(thousand),"%ld,%03ld",total_views/1000, total_views%1000);
     thousand[0] = ',';
     if (total_views>=10000000){
       thousand[1] = 0x20;
     }
     snprintf(million,sizeof(million),"%ld",total_views/1000000);
     strcpy(buf, million);
     strcat(buf, thousand);
  }

   if ((total_views>=1000) && (total_views<1000000)) {
     snprintf(buf,sizeof(buf),"%ld,%03ld",total_views/1000, total_views%1000);
   }
   
   if (total_views<1000)  {
     snprintf(buf,sizeof(buf),"%ld",total_views); 
     }
   MATRIX.print(buf);
   delay(10000);
}


void gettime() {
  
  timeClient.update();
  
  char clockdata[17];
  char formatted[10];
  char formattedDate[11];
  
  timeClient.getFormattedTime().toCharArray(formatted,6);

  strcpy(clockdata, daysOfTheWeek[timeClient.getDay()]);
  strcat(clockdata, "  ");
  strcat(clockdata, formatted);
  
  MATRIX.print(clockdata);
  delay(10000);   
}
  
  

void setup() {

  MATRIX.begin();  

  nexInit();
  
  client.setInsecure(); // Needed to get information for the YouTube API on the NodeMcu
  
  WiFi.begin(wifi_name, wifi_password);  // connect to the WiFi network
  
  while (WiFi.status() != WL_CONNECTED) {  // wait for a connection
    delay(500);
  }
  
  IPAddress ip = WiFi.localIP();

  timeClient.begin();
  
  MATRIX.setIntensity(1);
  sendCommand("dims=100");  // Set Nextion screen brightness to maximum

  
}

void loop() {

  chosen_quote=random(0, 23);  // Randomly choose a quote of the day
  strcpy(current_quote, quote_list[chosen_quote]); 
  page3.show();  // Change the page on the Nextion screen
  quotes();
  
  MATRIX.setTextAlignment(PA_CENTER);
  
  page0.show();
  gettime();
  
  page1.show();
  getsubs();
  
  page2.show();
  gettotalviews();
}
CONCLUSION

I didn’t want to go all crazy with this thing, and spend too much money or time.

All in all, I’m pretty happy with the results.

My favourite function is probably the ‘Quote of the Day’ thing, I get a laugh every time I get inside the workshop 🙂

I know this is like the millionth YouTube subscriber counter out there, but I hope you found this interesting.

Thanks for dropping by, and hope to see you in the next one.

Cheers!

TUTORIAL VIDEO
DOWNLOAD

Copy and Paste the above code/sketch in your Arduino IDE software.

Link to the libraries used in this tutorial:


Arduino YouTube Library by Brian Lough https://github.com/witnessmenow/arduino-youtube-api

ArduinoJson library written by Benoît Blanchon
– Install this library using the Arduino IDE Library manager
– You need to choose version 5.13.8 since the new versions will not work

Nextion Enhanced Library: https://github.com/jyberg/Enhanced-Nextion-Library

MD Parola Library: https://github.com/MajicDesigns/MD_Parola

MD MAX72xx Library: https://github.com/MajicDesigns/MD_MAX72xx

NTPClient Library: https://github.com/arduino-libraries/NTPClient

If you’re not sure how to install libraries this way, check out this tutorial video:
https://www.brainy-bits.com/arduino-libraries-tutorial/

By | 2019-10-18T19:38:50-04:00 October 18th, 2019|Tutorials|

Leave A Comment