The Dod 1 год назад
Сommit
5e13d6e316
6 измененных файлов: 431 добавлений и 0 удалений
  1. 3
    0
      .gitignore
  2. Двоичные данные
      2023-11-11-shtika-each-name-a-star-museum-photo-noam-amir.jpg
  3. 29
    0
      README.md
  4. 309
    0
      each-name-a-star.html
  5. 90
    0
      neopixel-twinkle/neopixel-twinkle.ino
  6. Двоичные данные
      starfield.png

+ 3
- 0
.gitignore Просмотреть файл

@@ -0,0 +1,3 @@
1
+work/
2
+*.swp
3
+*.backup

Двоичные данные
2023-11-11-shtika-each-name-a-star-museum-photo-noam-amir.jpg Просмотреть файл


+ 29
- 0
README.md Просмотреть файл

@@ -0,0 +1,29 @@
1
+**Each Name a Star** is an installation used as a centerpiece for meditation circles of [Roaring Silence](https://shtika2023.org).
2
+
3
+[![A meditation circle around the installation at the hostage vigil at Tel Aviv Museum square](2023-11-11-shtika-each-name-a-star-museum-photo-noam-amir.jpg)](https://cdn.masto.host/tooot/media_attachments/files/111/396/975/164/429/029/original/2f07a789e13175ae.mp4)
4
+A meditation circle around the installation at the hostage vigil at Tel Aviv Museum square, November 11, 2023. Photo: Noam Amir.
5
+
6
+#### [Video](https://cdn.masto.host/tooot/media_attachments/files/111/396/975/164/429/029/original/2f07a789e13175ae.mp4)
7
+
8
+### Each Name a Star
9
+
10
+The installation has 3 layers
11
+* A neopixel led strip (arranged in a spiral) driven by an Arduino running the [neopixel-twinkle](neopixel-twinkle) sketch.
12
+* A white sheet.
13
+* Projection from above of [each-name-a-star.html](each-name-a-star.html) with 180-degree rotated names (rotation makes sense when projected from above).
14
+
15
+### [each-name-a-star.html](https://zzzen.com/each-name-a-star.html) instructions
16
+
17
+If your projector can display a web browser, you can use the live version 
18
+
19
+* The page is online [here](https://zzzen.com/each-name-a-star.html).
20
+* Down arrow turns the names 180 degrees (Up arrow to reverse)
21
+* Left arrow hides star backdrop (Right arrow to reverse)
22
+
23
+### Static video files
24
+
25
+If your projector can only show local video files (e.g SD card or disk on key), here are two minute long videos:
26
+
27
+* [enas.mp4](enas.mp4) — Default settings
28
+* [enas180.mp4](enas180.mp4) — Names rotated 180-degrees (for projection from above).
29
+

+ 309
- 0
each-name-a-star.html Просмотреть файл

@@ -0,0 +1,309 @@
1
+
2
+<!DOCTYPE html>
3
+<html lang="he" dir="rtl">
4
+
5
+<head>
6
+    <meta charset="utf-8" />
7
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
8
+    <title>כל שם כוכב</title>
9
+    <!-- Google fonts-->
10
+    <link rel="preconnect" href="https://fonts.googleapis.com">
11
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
12
+    <link href="https://fonts.googleapis.com/css2?family=Alef:wght@700&display=swap" rel="stylesheet"> 
13
+    <style>
14
+    body {
15
+        font-family: Alef;
16
+        font-size: 3rem;
17
+        color: white;
18
+        background-color: black;
19
+        background-image: url('starfield.png');
20
+        background-size: cover;
21
+    }
22
+    .name {
23
+        position: fixed;
24
+    }
25
+    </style>
26
+</head>
27
+<body>
28
+
29
+<script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>
30
+<script>
31
+var CYCLE_MILLIS = 50;
32
+var P_TWINKLE = 0.23;
33
+var DECAY_FACTOR = 0.023;
34
+var CUTOFF_LEVEL = 0.1;
35
+
36
+function cycle() {
37
+    if (Math.random()<P_TWINKLE) {
38
+        $($(".name")[Math.floor(Math.random()*N)]).css("opacity", 1);
39
+    }
40
+    $(".name").each(function(index) {
41
+        var op = Number($(this).css("opacity"))*(1.0-DECAY_FACTOR);
42
+        $(this).css("opacity", op>CUTOFF_LEVEL? op: 0); 
43
+    });
44
+}
45
+
46
+var names = [
47
+    "Anucha",
48
+    "Gong",
49
+    "Komkrit",
50
+    "Manee",
51
+    "Natthaporn",
52
+    "Owat",
53
+    "Pattanayuth",
54
+    "אביב",
55
+    "אביב",
56
+    "אביבה",
57
+    "אביגיל",
58
+    "אבינתן",
59
+    "אביתר",
60
+    "אברהם",
61
+    "אגם",
62
+    "אגם",
63
+    "אהד",
64
+    "אוהד",
65
+    "אוהד",
66
+    "אופיר",
67
+    "אופיר",
68
+    "אופליה",
69
+    "אור",
70
+    "אור",
71
+    "אורי",
72
+    "אוריאל",
73
+    "אוריה",
74
+    "אוריון",
75
+    "אורן",
76
+    "איוון",
77
+    "אילן",
78
+    "אילנה",
79
+    "אירנה",
80
+    "איתי",
81
+    "איתי",
82
+    "איתי",
83
+    "איתן",
84
+    "איתן",
85
+    "איתן",
86
+    "איתן",
87
+    "אלה",
88
+    "אלון",
89
+    "אלון",
90
+    "אלי",
91
+    "אליה",
92
+    "אליה",
93
+    "אליהו",
94
+    "אליקים",
95
+    "אלכס",
96
+    "אלכסנדר",
97
+    "אלמה",
98
+    "אלמוג",
99
+    "אלמוג",
100
+    "אלעד",
101
+    "אלקנה",
102
+    "אמה",
103
+    "אמילי",
104
+    "אמיליה",
105
+    "אנדריי",
106
+    "אפרת",
107
+    "ארבל",
108
+    "ארז",
109
+    "אריאל",
110
+    "אריאל",
111
+    "אריה",
112
+    "בלאל",
113
+    "בר",
114
+    "גבריאלה",
115
+    "גד",
116
+    "גד",
117
+    "ג'ודי",
118
+    "ג'ושוע",
119
+    "ג'ושי",
120
+    "גיא",
121
+    "גיא",
122
+    "ג'ימי",
123
+    "גל",
124
+    "גלי",
125
+    "דוד",
126
+    "דוד",
127
+    "דולב",
128
+    "דורון",
129
+    "דורון",
130
+    "דיצה",
131
+    "דניאל",
132
+    "דניאל",
133
+    "דניאל",
134
+    "דפנה",
135
+    "דפנה",
136
+    "דרור",
137
+    "דרור",
138
+    "הגר",
139
+    "הילה",
140
+    "הירש",
141
+    "ויויאן",
142
+    "זיו",
143
+    "חיים",
144
+    "חמזה",
145
+    "חן",
146
+    "חנה",
147
+    "חנה",
148
+    "חנן",
149
+    "טל",
150
+    "טל",
151
+    "טל",
152
+    "טל",
153
+    "יאיר",
154
+    "יאיר",
155
+    "יגב",
156
+    "יגיל",
157
+    "יהודית",
158
+    "יהל",
159
+    "יובל",
160
+    "יובל",
161
+    "יולי",
162
+    "יונתן",
163
+    "יוסוף",
164
+    "יוסף",
165
+    "יוסף",
166
+    "יורם",
167
+    "יותם",
168
+    "ילנה",
169
+    "יפה",
170
+    "יצחק",
171
+    "יצחק",
172
+    "ירדן",
173
+    "ירדן",
174
+    "כפיר",
175
+    "כרמל",
176
+    "לואיס",
177
+    "ליאור",
178
+    "ליאם",
179
+    "ליאת",
180
+    "לירי",
181
+    "מורן",
182
+    "מיה",
183
+    "מיה",
184
+    "מייה",
185
+    "מייה",
186
+    "מיקה",
187
+    "מירב",
188
+    "מישל",
189
+    "מקסים",
190
+    "מרגלית",
191
+    "מתן",
192
+    "מתן",
193
+    "נדב",
194
+    "נוגה",
195
+    "נווה",
196
+    "נועה",
197
+    "נועה",
198
+    "נועם",
199
+    "נורלין",
200
+    "נילי",
201
+    "ניק",
202
+    "נמרוד",
203
+    "נעם",
204
+    "נעמה",
205
+    "סאמר",
206
+    "סהר",
207
+    "סהר",
208
+    "סוג'יט",
209
+    "ספיר",
210
+    "סשה",
211
+    "עאישה",
212
+    "עדה",
213
+    "עדי",
214
+    "עדינה",
215
+    "עדן",
216
+    "עדן",
217
+    "עודד",
218
+    "עומר",
219
+    "עומר",
220
+    "עומר",
221
+    "עומרי",
222
+    "עופר",
223
+    "עידן",
224
+    "עידן",
225
+    "עלמה",
226
+    "עמירם",
227
+    "עמית",
228
+    "עמית",
229
+    "עמית",
230
+    "ענבר",
231
+    "עפרה",
232
+    "עפרי",
233
+    "פאצ'קו",
234
+    "פרננדו",
235
+    "צחי",
236
+    "קאיד",
237
+    "קיריל",
238
+    "קית",
239
+    "קלמנס",
240
+    "קלרה",
241
+    "קרינה",
242
+    "קרינה",
243
+    "קרן",
244
+    "רביד",
245
+    "רום",
246
+    "רומי",
247
+    "רון",
248
+    "רון",
249
+    "רון",
250
+    "רוני",
251
+    "רונן",
252
+    "רותי",
253
+    "רז",
254
+    "רז",
255
+    "רימון",
256
+    "רן",
257
+    "רעיה",
258
+    "שגב",
259
+    "שגיא",
260
+    "שושן",
261
+    "שירי",
262
+    "שירי",
263
+    "שלומי",
264
+    "שלמה",
265
+    "שני",
266
+    "שני",
267
+    "שקד",
268
+    "שרון",
269
+    "שרון",
270
+    "תומר",
271
+    "תמיר",
272
+    "תמיר",
273
+    "תמר"
274
+];
275
+var N = names.length;
276
+$(() => {
277
+    for (i=0; i<N; i++) {
278
+        var div = $("<div/>").addClass("name").text(names[i]).css("opacity",0);
279
+        var yoffset = 50-Math.round(Math.random()*50.0*0.98);
280
+        var xoffset = Math.round(50.0-(Math.random()*50.0*0.7*Math.sin(Math.PI*0.5*(yoffset/50.0))));
281
+        // *(9.0/16.0)
282
+        if (Math.random()<0.5) {
283
+            div.css("left", xoffset.toString()+"vw");
284
+        } else {
285
+            div.css("right", xoffset.toString()+"vw");
286
+        }
287
+        if (Math.random()<0.5) {
288
+            div.css("top", yoffset.toString()+"vh");
289
+        } else {
290
+            div.css("bottom", yoffset.toString()+"vh");
291
+        }
292
+        $("body").append(div);
293
+    }
294
+    window.addEventListener('keydown', (event) => {
295
+        console.log(event.key);
296
+        if (event.key==="ArrowDown") {
297
+            $('.name').css("rotate", "180deg");
298
+        } else if (event.key==="ArrowUp") {
299
+            $('.name').css("rotate", "0deg");
300
+        } else if (event.key==="ArrowLeft") {
301
+            $('body').css("background-image", "none");
302
+        } else if (event.key==="ArrowRight") {
303
+            $('body').css("background-image", "url('starfield.png')").css("background-size", "cover");
304
+        }
305
+    });
306
+    setInterval(cycle, CYCLE_MILLIS);
307
+});
308
+</script>
309
+</body>

+ 90
- 0
neopixel-twinkle/neopixel-twinkle.ino Просмотреть файл

@@ -0,0 +1,90 @@
1
+// Twinkling neopixel led strip. Used for "Each name a star"
2
+// installation at hostage release vigils 2023
3
+// by Roaring Silence https://shtika2023.org
4
+
5
+// * Connect strip to pin 6, gnd, and +5V
6
+// * Set LED_COUNT according to your strip's LED counts
7
+// * You might need to change NEO_* arguments to fit your hardware
8
+
9
+// NEOPIXEL BEST PRACTICES for most reliable operation:
10
+// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
11
+// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
12
+// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
13
+// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
14
+//   connect GROUND (-) first, then +, then data.
15
+// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
16
+//   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
17
+// (Skipping these may work OK on your workbench but can fail in the field)
18
+
19
+#include <Adafruit_NeoPixel.h>
20
+#ifdef __AVR__
21
+#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
22
+#endif
23
+
24
+// Which pin on the Arduino is connected to the NeoPixels?
25
+// On a Trinket or Gemma we suggest changing this to 1:
26
+#define LED_PIN    6
27
+
28
+// How many NeoPixels are attached to the Arduino?
29
+#define LED_COUNT 55
30
+
31
+// Declare our NeoPixel strip object:
32
+Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_RGB + NEO_KHZ800);
33
+// Argument 1 = Number of pixels in NeoPixel strip
34
+// Argument 2 = Arduino pin number (most are valid)
35
+// Argument 3 = Pixel type flags, add together as needed:
36
+//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
37
+//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
38
+//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
39
+//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
40
+//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
41
+
42
+#define P_TWINKLE 0.15
43
+#define DECAY_FACTOR 0.023
44
+#define CUTOFF_LEVEL 0.1
45
+#define R_FACTOR 191
46
+#define G_FACTOR 127
47
+#define B_FACTOR 31
48
+
49
+#define CYCLE_MILLIS 23
50
+#define MIN_INITIAL 0.75
51
+#define MAX_INITIAL 1.0
52
+
53
+#define FRAND(minval, maxval) (random(minval*1000, maxval*1000)/1000.0)
54
+
55
+float levels[LED_COUNT] = { 0.0 };
56
+
57
+
58
+// setup() function -- runs once at startup --------------------------------
59
+
60
+void setup() {
61
+  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
62
+  // Any other board, you can remove this part (but no harm leaving it):
63
+#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
64
+  clock_prescale_set(clock_div_1);
65
+#endif
66
+  // END of Trinket-specific code.
67
+
68
+  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
69
+  strip.show();            // Turn OFF all pixels ASAP
70
+  strip.setBrightness(191); // Set BRIGHTNESS to about 1/5 (max = 255)
71
+}
72
+
73
+
74
+// loop() function -- runs repeatedly as long as board is on ---------------
75
+
76
+void loop() {
77
+  if (FRAND(0.0, 1.1) < P_TWINKLE) {
78
+    levels[random(0, LED_COUNT)] = FRAND(MIN_INITIAL, MAX_INITIAL);
79
+
80
+  }
81
+  for (int i = 0; i < LED_COUNT; i++) { // For each pixel in strip...
82
+    levels[i] *= (1 - DECAY_FACTOR);
83
+    if (levels[i] < CUTOFF_LEVEL) {
84
+      levels[i] = 0.0;
85
+    }
86
+    strip.setPixelColor(i, strip.Color(R_FACTOR * levels[i], G_FACTOR * levels[i], B_FACTOR * levels[i]));   //  Set pixel's color (in RAM)
87
+  }
88
+  strip.show();                          //  Update strip to match
89
+  delay(CYCLE_MILLIS);                           //  Pause for a moment
90
+}

Двоичные данные
starfield.png Просмотреть файл


Загрузка…
Отмена
Сохранить