Start

[In english]

Jellyfish 1

Av Hans Mehlin, 2021-01-10.

Jellyfish1 är en Arduino-driven lampa som ändrar färg och animationer baserat på rörelserna på aktiemarknaden.

Färgen på animationen indikerar om marknaden rör sig uppåt eller nedåt, medan hastigheten på animationerna indikerar hastigheten på rörelserna på marknaden. Färgerna är animerade som en cykel mellan två färger. Tentaklerna har en extra löpande vit pixel mellan varje färgcykel.

Exempel på animation som indikerar en positiv marknad med en hastighet på cirka 0,5% under 8 timmar:

Exempel på animation som indikerar en negativ marknad med en hastighet på cirka 0,5% under 8 timmar:

Hur den byggdes

Elektronik

Jellyfish 1 är baserad på ett NodeMCU V2 Arduino-kort med inbyggd WIFI, en NeoPixel Ring med 24 RGB-LED och 1 meter NeoPixel Digital RGBW LED-remsa som är uppdelad i 3 delar med 20 LED i varje. Kretsen drivs av extern 5V. En kondensator skyddar kretsen mot strömspikar och resistanser läggs till mellan den digitala utgången från Arduino och LED remsorna.

Kretsen testades först på ett experimentbräde, som också användes under utvecklingen av koden.

Kretsen löddes senare på ett universellt kort för att göra den mer robust och minska storleken. 5V-strömmen till Arduino kan enkelt kopplas bort när det behövs för att ansluta den till USB och uppdatera koden.

 

 

Kod

Arduino anropar en API-URL med regelbundna intervall för att hämta en json-fil med parametrar som styr färgerna och hastigheten på animationen.


// jellyfish 1 by Hans Mehlin

#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Arduino_JSON.h>

#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

const char* ssid     = "your ssid here";
const char* password = "your password here";

// Pin for controlling ledstrip
#define LED_PIN    D7
#define LED_PINR   D5

// Number of NeoPixels attached to the Arduino
#define LED_COUNT 20
#define LED_COUNTR 24

// Declare our NeoPixel strip objects:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_RGBW + NEO_KHZ800);
Adafruit_NeoPixel ring(LED_COUNTR, LED_PINR, NEO_GRB + NEO_KHZ800);

void setup() {

  Serial.begin(115200);         // Start the Serial communication to send messages to the computer
  delay(10);
  Serial.println('\n');
  
  WiFi.begin(ssid, password);             // Connect to the network
  Serial.print("Connecting to ");
  Serial.print(ssid); Serial.println(" ...");

  int i = 0;
  while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
    delay(1000);
    Serial.print(++i); Serial.print(' ');
  }

  Serial.println('\n');
  Serial.println("Connection established!");  
  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());         // Send the IP address of the ESP8266 to the computer

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(20); // Set BRIGHTNESS to 50 is about 1/5 (max = 255)

  ring.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  ring.show();            // Turn OFF all pixels ASAP
  ring.setBrightness(20); // Set BRIGHTNESS to 50 is about 1/5 (max = 255)
}

void loop() {

  int white = 0;
  int whitepixel = 80;
  int r1 = 0;
  int g1 = 0;
  int b1 = 255;
  int r2 = 0;
  int g2 = 255;
  int b2 = 0;
  int width = 20;
  int sleep = 50;

  float part;
  float rad;
  float s;
  int numtimes;
  int offsetr;

//Periodically refresh the variables from the web definition
  if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
    HTTPClient http;  //Declare an object of class HTTPClient
    http.begin("http://your-url-here/data.json");  //Specify request destination
    int httpCode = http.GET();                                                                  //Send the request
    if (httpCode > 0) { //Check the returning code
      String payload = http.getString();   //Get the request response payload
      Serial.println(payload);                     //Print the response payload
      //deserializeJson(vars, payload);
      JSONVar myObject = JSON.parse(payload);
      const char* name = myObject["name"];
      if (myObject.hasOwnProperty("color1")) {
        r1 = myObject["color1"][0];
        g1 = myObject["color1"][1];
        b1 = myObject["color1"][2];
      }
      if (myObject.hasOwnProperty("color2")) {
        r2 = myObject["color2"][0];
        g2 = myObject["color2"][1];
        b2 = myObject["color2"][2];
      }
      if (myObject.hasOwnProperty("width")) {
        width = myObject["width"];
      }
      if (myObject.hasOwnProperty("sleep")) {
        sleep = myObject["sleep"];
      }
      http.end();   //Close connection
    }
  }

  // Number of times to loop before we read the paramaters again
  // 1000000 = about 1 minute

  numtimes = 1000000/(LED_COUNT * width * sleep);
  if (numtimes <= 0) { numtimes = 1; }

  for(int bigloop=0; bigloop<numtimes; bigloop++) {

    for(int offset=0; offset<width; offset++) {
      offsetr = offsetr + 1;
      if (offsetr > LED_COUNTR) {offsetr = offsetr - LED_COUNTR - 1; }
	  
      for(int i=0; i<LED_COUNT; i++) { // For each pixel in strip...
        part = float(i - offset) / float(width);
        rad = part * 6,283;
        s = sin(rad);
        s = s + 1,0;
        s = s / 2,0;
        if (bigloop==0 && offset==0 && i==0) {
          Serial.println("i");
          Serial.println(i);
          Serial.println("s");
          Serial.println(s);
        }
        int r = int( float(r2-r1) * s + float(r1)); 
        int g = int( float(g2-g1) * s + float(g1));
        int b = int( float(b2-b1) * s + float(b1));
        int whitelevel = white;
//        if (i==offset || i==offset-LED_COUNT) { whitelevel = whitepixel; }
        if (i==offset) { whitelevel = whitepixel; }

        strip.setPixelColor(i, g, r, b, whitelevel);         //  Set pixel's color (in RAM)

        for(int j=0; j<LED_COUNTR; j++) { // For each pixel in ring...

          part = float(j - offsetr) / float(LED_COUNTR);
          rad = part * 6,283;
          s = sin(rad);
          s = s + 1,0;
          s = s / 2,0;
          if (bigloop==0 && offset==0 && i==0) {
            Serial.println("i");
            Serial.println(i);
            Serial.println("s");
            Serial.println(s);
          }
          int r = int( float(r2-r1) * s + float(r1)); 
          int g = int( float(g2-g1) * s + float(g1));
          int b = int( float(b2-b1) * s + float(b1));

          ring.setPixelColor(j, r, g, b);         //  Set pixel's color (in RAM)
        }
        ring.show();                          //  Update ring to match
      }
      strip.show();                         //  Update strip to match
      delay(sleep);  
    }
  }
}
	

Nedan finns ett exempel på en json-fil. I mitt fall är det inte en statisk json-fil utan en php-backend som returnerar json. Backend hämtar regelbundet mina index från aktiemarknaden och beräknar lämpliga färger och hastighet. Eftersom backend kod är ganska personlig är den inte inkluderad här. Genom att separera visualiseringen i Arduino och backend som returnerar json kan Yellyfish1 användas för att visualisera andra saker som väder eller sociala medier-analyser.

	
{
  "name": "Jellyfish1",
  "sleep": 150,
  "width": 60,
  "color1": [
    0,
    0,
    255
  ],
  "color2": [
    0,
    255,
    0
  ]
}
	
	

 

Montering

Kretsen monterades inuti en upp-och-nedvänd rund glasljusstake. Strömkabeln går genom ett borrat hål högst upp. LED-ringen monterades med ljuset uppåt tätt mot glaset för att sprida ljuset inuti glaset. Remsorna monterades som tentakler under glaset. En knut på strömkabeln håller den uppe och trådar håller ihop saker och tar bort stress från kablar.

Glaset täcktes med ett vitt oregelbundet och fluffigt tyg. För tentaklerna monterades en metalltråd i några band för att göra det möjligt att justera deras positioner och få dem att reflektera ljuset. Tyget kan enkelt tas bort, och kortet dras ut från glaset, om en programuppdatering behövs.

Webbsajten senast uppdaterad 2024-11
Copyright 2024 Vårboda Studio