Перейти к содержанию

Mendex

Members
  • Постов

    5
  • Зарегистрирован

  • Посещение

Электроника

  • Стаж в электронике
    1-2 года

Достижения Mendex

Новичок

Новичок (1/14)

  • Неделя на форуме
  • Месяц на форуме
  • Год на форуме

Последние значки

0

Репутация

  1. Само готовое устройство меня не так сильно интересует, как возможность отредактировать код под свои нужды. Что то поменять, что то добавить в этом весь фетишь. К том же проект задумывался как "открытый" чтобы любой желающий мог повторить подобное чудо. Так как готов поспорить что желающих будет много.
  2. Обыскал уже весь инет в поисках именно готового решения. Увы не нашёл. Именно на ленте из WS2812 и собирался делать данный проект.
  3. Так же нашёл забугорный форум где обсуждают именно этот же анализатор. https://forum.arduino.cc/index.php?topic=459979.0
  4. Как реализовать этот проект. Что куда подключить. Возможно лучше было бы использовать какой нить shield. например тот же Spectrum Shield который имеет вход и выход 3.5.
  5. В общем ребят тема такая. Хотелось бы сделать многополосный анализатор спектра на ленте WS2812B + arduino Было забугорное видео с инструкцией но его удалили. Осталась только картинка и скетч от готового анализатора. Из за недостатка знаний сам построить не могу. Поэтому прошу более прошареных умов. Этого видео больше нет. Но выглядел анализатор именно так. Code Repository: https://www.dropbox.com/sh/g3qraziuimksdho/AADwkqKRP3JmV9tQyGD_z2jga?dl=0 Строго не судите. Это моё первое обращение на форуме. Посоветуйте как реализовать этот проект #define PIXELS 600 // Number of pixels in the string // These values depend on which pin your string is connected to and what board you are using // More info on how to find these at http://www.arduino.cc/en/Reference/PortManipulation #define PIXEL_PORT PORTD // Port of the pin the pixels are connected to #define PIXEL_DDR DDRD // Port of the pin the pixels are connected to #define PIXEL_BIT 6 // Bit of the pin the pixels are connected to #define NUM_COLS 30 // Number of columns in our neopixel matrix #define NUM_ROWS 20 // Number of rows in our neopixel matrix // These are the timing constraints taken mostly from the WS2812 datasheets // These are chosen to be conservative and avoid problems rather than for maximum throughput #define T1H 900 // Width of a 1 bit in ns #define T1L 600 // Width of a 1 bit in ns #define T0H 400 // Width of a 0 bit in ns #define T0L 900 // Width of a 0 bit in ns #define RES 6000 // Width of the low gap between bits to cause a frame to latch // Here are some convience defines for using nanoseconds specs to generate actual CPU delays #define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives #define CYCLES_PER_SEC (F_CPU) #define NS_PER_CYCLE ( NS_PER_SEC / CYCLES_PER_SEC ) #define NS_TO_CYCLES(n) ( (n) / NS_PER_CYCLE ) // My spectrum analyzer produces a rainbow effect as amplitudes increase // This is a lookup table of sorts for the appropriate color of a specific amplitude (RGB) // I found the values online in RGB format so I left them that way and corrected for it later... uint8_t Rainbow[60] = {0xbf, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x40, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x40, 0xff, 0x00, 0x7f, 0xff, 0x00, 0xbf, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xbf, 0x00, 0xff, 0x80, 0x00, 0xff, 0x40, 0x00, 0xff, 0x00, 0x40, 0xff, 0x00, 0x80, 0xff, 0x00, 0xbf, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xbf, 0x00, 0xff, 0x80, 0x00, 0xff, 0x40, 0x00, 0xff, 0x00, 0x00}; // Actually send a bit to the string. We must to drop to asm to enusre that the complier does // not reorder things and make it so the delay happens in the wrong place. void sendBit( bool bitVal ) { if ( bitVal ) { // 0 bit asm volatile ( "sbi %[port], %[bit] \n\t" // Set the output bit ".rept %[onCycles] \n\t" // Execute NOPs to delay exactly the specified number of cycles "nop \n\t" ".endr \n\t" "cbi %[port], %[bit] \n\t" // Clear the output bit ".rept %[offCycles] \n\t" // Execute NOPs to delay exactly the specified number of cycles "nop \n\t" ".endr \n\t" :: [port] "I" (_SFR_IO_ADDR(PIXEL_PORT)), [bit] "I" (PIXEL_BIT), [onCycles] "I" (NS_TO_CYCLES(T1H) - 2), // 1-bit width less overhead for the actual bit setting, note that this delay could be longer and everything would still work [offCycles] "I" (NS_TO_CYCLES(T1L) - 2) // Minimum interbit delay. Note that we probably don't need this at all since the loop overhead will be enough, but here for correctness ); } else { // 1 bit // ************************************************************************** // This line is really the only tight goldilocks timing in the whole program! // ************************************************************************** asm volatile ( "sbi %[port], %[bit] \n\t" // Set the output bit ".rept %[onCycles] \n\t" // Now timing actually matters. The 0-bit must be long enough to be detected but not too long or it will be a 1-bit "nop \n\t" // Execute NOPs to delay exactly the specified number of cycles ".endr \n\t" "cbi %[port], %[bit] \n\t" // Clear the output bit ".rept %[offCycles] \n\t" // Execute NOPs to delay exactly the specified number of cycles "nop \n\t" ".endr \n\t" :: [port] "I" (_SFR_IO_ADDR(PIXEL_PORT)), [bit] "I" (PIXEL_BIT), [onCycles] "I" (NS_TO_CYCLES(T0H) - 2), [offCycles] "I" (NS_TO_CYCLES(T0L) - 2) ); } // Note that the inter-bit gap can be as long as you want as long as it doesn't exceed the 5us reset timeout (which is A long time) // Here I have been generous and not tried to squeeze the gap tight but instead erred on the side of lots of extra time. // This has thenice side effect of avoid glitches on very long strings becuase } void sendByte( uint8_t sByte ) { for( unsigned char bit = 0 ; bit < 8 ; bit++ ) { sendBit( bitRead( sByte , 7 ) ); // Neopixel wants bit in highest-to-lowest order // so send highest bit (bit #7 in an 8-bit byte since they start at 0) sByte <<= 1; // and then shift left so bit 6 moves into 7, 5 moves into 6, etc } } /* The following three functions are the public API: ledSetup() - set up the pin that is connected to the string. Call once at the begining of the program. setBrightness(byte) - changes the brightness of the neopixels (0(low)->255(high)) setMatrix(*byte, byte[]) - Converts a byte array of amplitudes into appropriate pixel orientation for matrix clear() - writes 0's to all pixels to clear the matrix show(*byte) - push updated pixel data to the matrix */ /************ledSetup()******************/ /// Description: declare which i/o pin will be sending data /// * Must be called prior to using neopixels /// Parameters: NONE /// Return: NONE /****************************************/ void ledSetup() { bitSet( PIXEL_DDR , PIXEL_BIT ); } /************setBrightness()******************/ /// Description: changes brightness of neopixels /// * If not called, defaults to 255 /// Parameters: value - value between 0-255 to signify fraction of 100% brightness /// Return: NONE /*********************************************/ uint8_t Brightness = 255; void setBrightness(uint8_t value) { Brightness = value; return; } /************setMatrix()******************/ /// Description: Takes a NUM_COLS-long byte-array consisting of /// amplitudes for each column of the matrix, and /// populates the pixels array accordingly /// Parameters: Bars - byte array of new amplitudes /// pixels - byte array that will hold data for each pixel /// Return: NONE /*****************************************/ void setMatrix(uint8_t * Bars, uint8_t pixels[]) { uint16_t k = 0; // Scan column by column populating each pixel row by row for(int i = 0; i < NUM_COLS; i++) { for(int j = 0; j < NUM_ROWS; j++) { // For even valued columns, scan from bottom to top of column if(j <= (uint8_t)Bars[i]) { // If the row we are looking at is less than the amplitude in question pixels[k++] = Rainbow[j*3+1]; // then the neopixel should be active with the color found in the color lookup table above pixels[k++] = Rainbow[j*3]; // ******* Make sure that your values are in GRB format!!!! ******** pixels[k++] = Rainbow[j*3+2]; } else { // If the current row is greater than the amplitude in question pixels[k++] = 0; // leave the pixel blank pixels[k++] = 0; pixels[k++] = 0; } } i++; // Each loop will actually examine 2 columns rather than just one... for(int j = NUM_ROWS-1; j >= 0; j--) {// because odd valued columns were wired upside-down for convenience if(j <= (uint8_t)Bars[i]) { // So rather than scanning bottom to top, scan top to bottom now pixels[k++] = Rainbow[j*3+1]; // since the pixels array will be fed into the neopixels serially pixels[k++] = Rainbow[j*3]; // you'll need this column to be placed backwards in the array... pixels[k++] = Rainbow[j*3+2]; } else { pixels[k++] = 0; pixels[k++] = 0; pixels[k++] = 0; } } } return; } /************Clear()*********************/ /// Description: Send all 0s to the matrix /// Parameters: NONE /// Return: NONE /****************************************/ void Clear() { cli(); // Turn off all interrupts while we send data to the matrix for(int i = 0; i < PIXELS; i++) { sendByte(0); sendByte(0); sendByte(0); } sei(); // All of the data is sent so we can turn back on interrupts // By sending creating a specifically timed delay, the neopixels will know that we are done sending data _delay_us( (RES / 1000UL) + 1); // Round up since the delay must be _at_least_ this long (too short might not work, too long not a problem) } // Just wait long enough without sending any bits to cause the pixels to latch and display the last sent frame /************show()******************/ /// Description: "Refresh" the neopixel matrix with /// updated values /// * Should be called once the pixel array /// is updated and ready to be pushed /// Parameters: pixels - the byte array containing values for all the pixels /// Return: NONE /************************************/ void show(uint8_t * pixels) { cli(); // Turn off all interrupts while we send new data for(int i = 0; i < PIXELS*3; i++) { if(pixels[i] != 0 && Brightness != 0) { sendByte(((Brightness * pixels[i]) >> 8) + 1); // This is when we take pixel brightness into account } else { sendByte(0); } } sei(); // All data is sent so we can turn interrupts back on // By sending creating a specifically timed delay, the neopixels will know that we are done sending data _delay_us( (RES / 1000UL) + 1); // Round up since the delay must be _at_least_ this long (too short might not work, too long not a problem) return; }
×
×
  • Создать...