2140浏览
查看: 2140|回复: 61

[项目] 【Arduino】168种传感器系列实验(207)--- HT16k33 LED8*8点阵I2C

[复制链接]
本帖最后由 驴友花雕 于 2021-9-14 08:40 编辑

37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试多做实验,不管成功与否,都会记录下来——小小的进步或是搞不掂的问题,希望能够抛砖引玉。

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百零七:I2C红色8*8LED点阵模块HT16k33(VK16K33)驱动1088BS树莓派物联网可扩展编程


0 (1).jpg

0 (2).jpg



驴友花雕  初级技神
 楼主|

发表于 2021-9-11 16:18:30

  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  项目十九:Arduino 的小型音频可视化

  实验开源代码

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  4.   项目十九:Arduino 的小型音频可视化
  5.   模块接线:
  6.   - 3.3V 至麦克风放大器 + 和 Arduino AREF 引脚 <-- 重要!
  7.   MAX9814  Arduino
  8.   VCC        3.3V
  9.   GND        GND
  10.   OUT         A0
  11.   VK16k33    UNO
  12.   VIN        5V
  13.   GND        GND
  14.   SCL        A5
  15.   SDA        A4
  16. */
  17. // 重要提示:FFT_N 应该在 ffft.h 中 #defined 为 128。
  18. #include <avr/pgmspace.h>
  19. #include <ffft.h>
  20. #include <math.h>
  21. #include <Wire.h>
  22. #include <Adafruit_GFX.h>
  23. #include <Adafruit_LEDBackpack.h>
  24. // Microphone connects to Analog Pin 0.  Corresponding ADC channel number
  25. // varies among boards...it's ADC0 on Uno and Mega, ADC7 on Leonardo.
  26. // Other boards may require different settings; refer to datasheet.
  27. #ifdef __AVR_ATmega32U4__
  28. #define ADC_CHANNEL 7
  29. #else
  30. #define ADC_CHANNEL 0
  31. #endif
  32. int16_t       capture[FFT_N];    // Audio capture buffer
  33. complex_t     bfly_buff[FFT_N];  // FFT "butterfly" buffer
  34. uint16_t      spectrum[FFT_N / 2]; // Spectrum output buffer
  35. volatile byte samplePos = 0;     // Buffer position counter
  36. byte
  37. peak[8],      // Peak level of each column; used for falling dots
  38.      dotCount = 0, // Frame counter for delaying dot-falling speed
  39.      colCount = 0; // Frame counter for storing past column data
  40. int
  41. col[8][10],   // Column levels for the prior 10 frames
  42.     minLvlAvg[8], // For dynamic adjustment of low & high ends of graph,
  43.     maxLvlAvg[8], // pseudo rolling averages for the prior few frames.
  44.     colDiv[8];    // Used when filtering FFT output to 8 columns
  45. /*
  46.   These tables were arrived at through testing, modeling and trial and error,
  47.   exposing the unit to assorted music and sounds.  But there's no One Perfect
  48.   EQ Setting to Rule Them All, and the graph may respond better to some
  49.   inputs than others.  The software works at making the graph interesting,
  50.   but some columns will always be less lively than others, especially
  51.   comparing live speech against ambient music of varying genres.
  52. */
  53. static const uint8_t PROGMEM
  54. // This is low-level noise that's subtracted from each FFT output column:
  55. noise[64] = { 8, 6, 6, 5, 3, 4, 4, 4, 3, 4, 4, 3, 2, 3, 3, 4,
  56.               2, 1, 2, 1, 3, 2, 3, 2, 1, 2, 3, 1, 2, 3, 4, 4,
  57.               3, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2,
  58.               2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4
  59.             },
  60.             // These are scaling quotients for each FFT output column, sort of a
  61.             // graphic EQ in reverse.  Most music is pretty heavy at the bass end.
  62. eq[64] = {
  63.   255, 175, 218, 225, 220, 198, 147, 99, 68, 47, 33, 22, 14,  8,  4,  2,
  64.   0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  65.   0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  66.   0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
  67. },
  68. // When filtering down to 8 columns, these tables contain indexes
  69. // and weightings of the FFT spectrum output values to use.  Not all
  70. // buckets are used -- the bottom-most and several at the top are
  71. // either noisy or out of range or generally not good for a graph.
  72. col0data[] = {  2,  1,  // # of spectrum bins to merge, index of first
  73.                 111,   8
  74.              },           // Weights for each bin
  75.              col1data[] = {  4,  1,  // 4 bins, starting at index 1
  76.                              19, 186,  38,   2
  77.                           }, // Weights for 4 bins.  Got it now?
  78.                           col2data[] = {  5,  2,
  79.                                           11, 156, 118,  16,   1
  80.                                        },
  81.                                        col3data[] = {  8,  3,
  82.                                                        5,  55, 165, 164,  71,  18,   4,   1
  83.                                                     },
  84.                                            col4data[] = { 11,  5,
  85.                                                           3,  24,  89, 169, 178, 118,  54,  20,   6,   2,   1
  86.                                                         },
  87.                                                col5data[] = { 17,  7,
  88.                                                               2,   9,  29,  70, 125, 172, 185, 162, 118, 74,
  89.                                                               41,  21,  10,   5,   2,   1,   1
  90.                                                             },
  91.                                                    col6data[] = { 25, 11,
  92.                                                                   1,   4,  11,  25,  49,  83, 121, 156, 180, 185,
  93.                                                                   174, 149, 118,  87,  60,  40,  25,  16,  10,   6,
  94.                                                                   4,   2,   1,   1,   1
  95.                                                                 },
  96.                                                        col7data[] = { 37, 16,
  97.                                                                       1,   2,   5,  10,  18,  30,  46,  67,  92, 118,
  98.                                                                       143, 164, 179, 185, 184, 174, 158, 139, 118,  97,
  99.                                                                       77,  60,  45,  34,  25,  18,  13,   9,   7,   5,
  100.                                                                       3,   2,   2,   1,   1,   1,   1
  101.                                                                     },
  102.                                                            // And then this points to the start of the data for each of the columns:
  103. * const colData[]  = {
  104.   col0data, col1data, col2data, col3data,
  105.   col4data, col5data, col6data, col7data
  106. };
  107. Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
  108. void setup() {
  109.   uint8_t i, j, nBins, binNum, *data;
  110.   memset(peak, 0, sizeof(peak));
  111.   memset(col , 0, sizeof(col));
  112.   for (i = 0; i < 8; i++) {
  113.     minLvlAvg[i] = 0;
  114.     maxLvlAvg[i] = 512;
  115.     data         = (uint8_t *)pgm_read_word(&colData[i]);
  116.     nBins        = pgm_read_byte(&data[0]) + 2;
  117.     binNum       = pgm_read_byte(&data[1]);
  118.     for (colDiv[i] = 0, j = 2; j < nBins; j++)
  119.       colDiv[i] += pgm_read_byte(&data[j]);
  120.   }
  121.   matrix.begin(0x70);
  122.   // Init ADC free-run mode; f = ( 16MHz/prescaler ) / 13 cycles/conversion
  123.   ADMUX  = ADC_CHANNEL; // Channel sel, right-adj, use AREF pin
  124.   ADCSRA = _BV(ADEN)  | // ADC enable
  125.            _BV(ADSC)  | // ADC start
  126.            _BV(ADATE) | // Auto trigger
  127.            _BV(ADIE)  | // Interrupt enable
  128.            _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128:1 / 13 = 9615 Hz
  129.   ADCSRB = 0;                // Free run mode, no high MUX bit
  130.   DIDR0  = 1 << ADC_CHANNEL; // Turn off digital input for ADC pin
  131.   TIMSK0 = 0;                // Timer0 off
  132.   sei(); // Enable interrupts
  133. }
  134. void loop() {
  135.   uint8_t  i, x, L, *data, nBins, binNum, weighting, c;
  136.   uint16_t minLvl, maxLvl;
  137.   int      level, y, sum;
  138.   while (ADCSRA & _BV(ADIE)); // Wait for audio sampling to finish
  139.   fft_input(capture, bfly_buff);   // Samples -> complex #s
  140.   samplePos = 0;                   // Reset sample counter
  141.   ADCSRA |= _BV(ADIE);             // Resume sampling interrupt
  142.   fft_execute(bfly_buff);          // Process complex data
  143.   fft_output(bfly_buff, spectrum); // Complex -> spectrum
  144.   // Remove noise and apply EQ levels
  145.   for (x = 0; x < FFT_N / 2; x++) {
  146.     L = pgm_read_byte(&noise[x]);
  147.     spectrum[x] = (spectrum[x] <= L) ? 0 :
  148.                   (((spectrum[x] - L) * (256L - pgm_read_byte(&eq[x]))) >> 8);
  149.   }
  150.   // Fill background w/colors, then idle parts of columns will erase
  151.   matrix.fillRect(0, 0, 8, 3, LED_RED);    // Upper section
  152.   matrix.fillRect(0, 3, 8, 2, LED_YELLOW); // Mid
  153.   matrix.fillRect(0, 5, 8, 3, LED_GREEN);  // Lower section
  154.   // Downsample spectrum output to 8 columns:
  155.   for (x = 0; x < 8; x++) {
  156.     data   = (uint8_t *)pgm_read_word(&colData[x]);
  157.     nBins  = pgm_read_byte(&data[0]) + 2;
  158.     binNum = pgm_read_byte(&data[1]);
  159.     for (sum = 0, i = 2; i < nBins; i++)
  160.       sum += spectrum[binNum++] * pgm_read_byte(&data[i]); // Weighted
  161.     col[x][colCount] = sum / colDiv[x];                    // Average
  162.     minLvl = maxLvl = col[x][0];
  163.     for (i = 1; i < 10; i++) { // Get range of prior 10 frames
  164.       if (col[x][i] < minLvl)      minLvl = col[x][i];
  165.       else if (col[x][i] > maxLvl) maxLvl = col[x][i];
  166.     }
  167.     // minLvl and maxLvl indicate the extents of the FFT output, used
  168.     // for vertically scaling the output graph (so it looks interesting
  169.     // regardless of volume level).  If they're too close together though
  170.     // (e.g. at very low volume levels) the graph becomes super coarse
  171.     // and 'jumpy'...so keep some minimum distance between them (this
  172.     // also lets the graph go to zero when no sound is playing):
  173.     if ((maxLvl - minLvl) < 8) maxLvl = minLvl + 8;
  174.     minLvlAvg[x] = (minLvlAvg[x] * 7 + minLvl) >> 3; // Dampen min/max levels
  175.     maxLvlAvg[x] = (maxLvlAvg[x] * 7 + maxLvl) >> 3; // (fake rolling average)
  176.     // Second fixed-point scale based on dynamic min/max levels:
  177.     level = 10L * (col[x][colCount] - minLvlAvg[x]) /
  178.             (long)(maxLvlAvg[x] - minLvlAvg[x]);
  179.     // Clip output and convert to byte:
  180.     if (level < 0L)      c = 0;
  181.     else if (level > 10) c = 10; // Allow dot to go a couple pixels off top
  182.     else                c = (uint8_t)level;
  183.     if (c > peak[x]) peak[x] = c; // Keep dot on top
  184.     if (peak[x] <= 0) { // Empty column?
  185.       matrix.drawLine(x, 0, x, 7, LED_OFF);
  186.       continue;
  187.     } else if (c < 8) { // Partial column?
  188.       matrix.drawLine(x, 0, x, 7 - c, LED_OFF);
  189.     }
  190.     // The 'peak' dot color varies, but doesn't necessarily match
  191.     // the three screen regions...yellow has a little extra influence.
  192.     y = 8 - peak[x];
  193.     if (y < 2)      matrix.drawPixel(x, y, LED_RED);
  194.     else if (y < 6) matrix.drawPixel(x, y, LED_YELLOW);
  195.     else           matrix.drawPixel(x, y, LED_GREEN);
  196.   }
  197.   matrix.writeDisplay();
  198.   // Every third frame, make the peak pixels drop by 1:
  199.   if (++dotCount >= 3) {
  200.     dotCount = 0;
  201.     for (x = 0; x < 8; x++) {
  202.       if (peak[x] > 0) peak[x]--;
  203.     }
  204.   }
  205.   if (++colCount >= 10) colCount = 0;
  206. }
  207. ISR(ADC_vect) { // Audio-sampling interrupt
  208.   static const int16_t noiseThreshold = 4;
  209.   int16_t              sample         = ADC; // 0-1023
  210.   capture[samplePos] =
  211.     ((sample > (512 - noiseThreshold)) &&
  212.      (sample < (512 + noiseThreshold))) ? 0 :
  213.     sample - 512; // Sign-convert for FFT; -512 to +511
  214.   if (++samplePos >= FFT_N) ADCSRA &= ~_BV(ADIE); // Buffer full, interrupt off
  215. }
复制代码


回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-11 11:13:15

  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  项目十八:随机的眨眼睛

  实验开源代码

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  4.   项目十八:随机的眨眼睛
  5.   实验接线:
  6.   VK16k33    UNO
  7.   VIN        5V
  8.   GND        GND
  9.   SCL        A5
  10.   SDA        A4
  11. */
  12. #include <Arduino.h>
  13. #include <Wire.h>
  14. #include <Adafruit_GFX.h>
  15. #include <WaveHC.h>
  16. #include <WaveUtil.h>
  17. #include "Adafruit_LEDBackpack.h"
  18. // These WAV files should be in the root level of the SD card:
  19. static const char PROGMEM
  20.   wav0[] = "beware_i.wav",
  21.   wav1[] = "ihunger.wav",
  22.   wav2[] = "run_cowd.wav";
  23. static const char * const wavname[] PROGMEM = { wav0, wav1, wav2 };
  24. // PROGMEM makes frequent appearances throughout this code, reason being that
  25. // the SD card library requires gobs of precious RAM (leaving very little to
  26. // our own sketch).  PROGMEM lets us put fixed data into program flash memory,
  27. // which is considerably more spacious.  String tables are paritcularly nasty.
  28. // See www.arduino.cc/en/Reference/PROGMEM for more info.
  29. SdReader  card; // This object holds the information for the card
  30. FatVolume vol;  // This holds the information for the partition on the card
  31. FatReader root; // This holds the information for the volumes root directory
  32. FatReader file; // This object represent the WAV file for a phrase
  33. WaveHC    wave; // A single wave object -- only one sound is played at a time
  34. // Because the two eye matrices share the same address, only four
  35. // matrix objects are needed for the five displays:
  36. #define MATRIX_EYES         0
  37. #define MATRIX_MOUTH_LEFT   1
  38. #define MATRIX_MOUTH_MIDDLE 2
  39. #define MATRIX_MOUTH_RIGHT  3
  40. Adafruit_8x8matrix matrix[4] = { // Array of Adafruit_8x8matrix objects
  41.   Adafruit_8x8matrix(), Adafruit_8x8matrix(),
  42.   Adafruit_8x8matrix(), Adafruit_8x8matrix() };
  43. // Rather than assigning matrix addresses sequentially in a loop, each
  44. // has a spot in this array.  This makes it easier if you inadvertently
  45. // install one or more matrices in the wrong physical position --
  46. // re-order the addresses in this table and you can still refer to
  47. // matrices by index above, no other code or wiring needs to change.
  48. static const uint8_t PROGMEM matrixAddr[] = { 0x70, 0x71, 0x72, 0x73 };
  49. static const uint8_t PROGMEM // Bitmaps are stored in program memory
  50.   blinkImg[][8] = {    // Eye animation frames
  51.   { B00111100,         // Fully open eye
  52.     B01111110,
  53.     B11111111,
  54.     B11111111,
  55.     B11111111,
  56.     B11111111,
  57.     B01111110,
  58.     B00111100 },
  59.   { B00000000,
  60.     B01111110,
  61.     B11111111,
  62.     B11111111,
  63.     B11111111,
  64.     B11111111,
  65.     B01111110,
  66.     B00111100 },
  67.   { B00000000,
  68.     B00000000,
  69.     B00111100,
  70.     B11111111,
  71.     B11111111,
  72.     B11111111,
  73.     B00111100,
  74.     B00000000 },
  75.   { B00000000,
  76.     B00000000,
  77.     B00000000,
  78.     B00111100,
  79.     B11111111,
  80.     B01111110,
  81.     B00011000,
  82.     B00000000 },
  83.   { B00000000,         // Fully closed eye
  84.     B00000000,
  85.     B00000000,
  86.     B00000000,
  87.     B10000001,
  88.     B01111110,
  89.     B00000000,
  90.     B00000000 } },
  91.   mouthImg[][24] = {                 // Mouth animation frames
  92.   { B00000000, B00000000, B00000000, // Mouth position A
  93.     B00000000, B00000000, B00000000,
  94.     B01111111, B11111111, B11111110,
  95.     B00000000, B00000000, B00000000,
  96.     B00000000, B00000000, B00000000,
  97.     B00000000, B00000000, B00000000,
  98.     B00000000, B00000000, B00000000,
  99.     B00000000, B00000000, B00000000 },
  100.   { B00000000, B00000000, B00000000, // Mouth position B
  101.     B00000000, B00000000, B00000000,
  102.     B00111111, B11111111, B11111100,
  103.     B00000111, B00000000, B11100000,
  104.     B00000000, B11111111, B00000000,
  105.     B00000000, B00000000, B00000000,
  106.     B00000000, B00000000, B00000000,
  107.     B00000000, B00000000, B00000000 },
  108.   { B00000000, B00000000, B00000000, // Mouth position C
  109.     B00000000, B00000000, B00000000,
  110.     B00111111, B11111111, B11111100,
  111.     B00001000, B00000000, B00010000,
  112.     B00000110, B00000000, B01100000,
  113.     B00000001, B11000011, B10000000,
  114.     B00000000, B00111100, B00000000,
  115.     B00000000, B00000000, B00000000 },
  116.   { B00000000, B00000000, B00000000, // Mouth position D
  117.     B00000000, B00000000, B00000000,
  118.     B00111111, B11111111, B11111100,
  119.     B00100000, B00000000, B00000100,
  120.     B00010000, B00000000, B00001000,
  121.     B00001100, B00000000, B00110000,
  122.     B00000011, B10000001, B11000000,
  123.     B00000000, B01111110, B00000000 },
  124.   { B00000000, B00000000, B00000000, // Mouth position E
  125.     B00000000, B00111100, B00000000,
  126.     B00011111, B11000011, B11111000,
  127.     B00000011, B10000001, B11000000,
  128.     B00000000, B01111110, B00000000,
  129.     B00000000, B00000000, B00000000,
  130.     B00000000, B00000000, B00000000,
  131.     B00000000, B00000000, B00000000 },
  132.   { B00000000, B00111100, B00000000, // Mouth position F
  133.     B00000000, B11000011, B00000000,
  134.     B00001111, B00000000, B11110000,
  135.     B00000001, B00000000, B10000000,
  136.     B00000000, B11000011, B00000000,
  137.     B00000000, B00111100, B00000000,
  138.     B00000000, B00000000, B00000000,
  139.     B00000000, B00000000, B00000000 } };
  140. // Animation sequences corresponding to each WAV.  First number in
  141. // each pair is a mouth bitmap index.  Second number is the hold
  142. // time (in frames).  255 marks end of list.
  143. // There is no 'magic' here, the software is NOT deriving mouth
  144. // position from the sound...the tables were determined by hand,
  145. // just as animators do it.  Further explanation here:
  146. // http://www.idleworm.com/how/anm/03t/talk1.shtml
  147. static const uint8_t PROGMEM
  148.   seq1[] = { 0, 2,   2, 5,   5, 3,   3, 7, // "Beware, I live!"
  149.              4, 5,   3, 4,   2, 5,   4, 3,
  150.              3, 4,   1, 5,   3, 5,    255 },
  151.   seq2[] = { 0, 1,   3, 5,   1, 5,   4, 2, // "I hunger!"
  152.              3, 2,   1, 2,   4, 4,   1, 3,
  153.              4, 2,   255 },
  154.   seq3[] = { 0, 1,   1, 2,   3, 6,   2, 5, // "Run, coward!"
  155.              0, 1,   4, 4,   5, 2,   1, 5,
  156.              3, 6,   1, 4,    255 };
  157. static const uint8_t * const anim[] = { seq1, seq2, seq3 };
  158. const uint8_t
  159.   blinkIndex[] PROGMEM = { 1, 2, 3, 4, 3, 2, 1 }; // Blink bitmap sequence
  160. uint8_t
  161.   blinkCountdown = 100, // Countdown to next blink (in frames)
  162.   gazeCountdown  =  75, // Countdown to next eye movement
  163.   gazeFrames     =  50, // Duration of eye movement (smaller = faster)
  164.   mouthPos       =   0, // Current image number for mouth
  165.   mouthCountdown =  10, // Countdown to next mouth change
  166.   newPos         = 255, // New mouth position for current frame
  167.   *seq,                 // Animation sequence currently being played back
  168.   idx,                  // Current array index within animation sequence
  169.   prevBtn        = 99,  // Button # pressed on last loop() iteration
  170.   btnCount       = 0;   // Number of iterations same button has been held
  171. int8_t
  172.   eyeX = 3, eyeY = 3,   // Current eye position
  173.   newX = 3, newY = 3,   // Next eye position
  174.   dX   = 0, dY   = 0;   // Distance from prior to new position
  175. void setup() {
  176.   Serial.begin(9600);           
  177.   
  178.   Serial.println(F("WAV face"));
  179.   
  180.   if(!card.init())        Serial.println(F("Card init. failed!"));
  181.   if(!vol.init(card))     Serial.println(F("No partition!"));
  182.   if(!root.openRoot(vol)) Serial.println(F("Couldn't open dir"));
  183.   Serial.println(F("Files found:"));
  184.   root.ls();
  185.   // Seed random number generator from an unused analog input:
  186.   randomSeed(analogRead(A0));
  187.   // Initialize each matrix object:
  188.   for(uint8_t i=0; i<4; i++) {
  189.     matrix[i].begin(pgm_read_byte(&matrixAddr[i]));
  190.     // If using 'small' (1.2") displays vs. 'mini' (0.8"), enable this:
  191.     // matrix[i].setRotation(3);
  192.   }
  193.   // Enable pull-up resistors on three button inputs.
  194.   // Other end of each button then connects to GND.
  195.   for(uint8_t i=6; i<=8; i++) {
  196.     pinMode(i, INPUT);
  197.     digitalWrite(i, HIGH); // Enable pullup
  198.   }
  199. }
  200. void loop() {
  201.   uint8_t i;
  202.   // Draw eyeball in current state of blinkyness (no pupil).
  203.   matrix[MATRIX_EYES].clear();
  204.   matrix[MATRIX_EYES].drawBitmap(0, 0,
  205.     blinkImg[
  206.       (blinkCountdown < sizeof(blinkIndex)) ?      // Currently blinking?
  207.       pgm_read_byte(&blinkIndex[blinkCountdown]) : // Yes, look up bitmap #
  208.       0                                            // No, show bitmap 0
  209.     ], 8, 8, LED_ON);
  210.   // Decrement blink counter.  At end, set random time for next blink.
  211.   if(--blinkCountdown == 0) blinkCountdown = random(5, 180);
  212.   if(--gazeCountdown <= gazeFrames) {
  213.     // Eyes are in motion - draw pupil at interim position
  214.     matrix[MATRIX_EYES].fillRect(
  215.       newX - (dX * gazeCountdown / gazeFrames),
  216.       newY - (dY * gazeCountdown / gazeFrames),
  217.       2, 2, LED_OFF);
  218.     if(gazeCountdown == 0) {    // Last frame?
  219.       eyeX = newX; eyeY = newY; // Yes.  What's new is old, then...
  220.       do { // Pick random positions until one is within the eye circle
  221.         newX = random(7); newY = random(7);
  222.         dX   = newX - 3;  dY   = newY - 3;
  223.       } while((dX * dX + dY * dY) >= 10);      // Thank you Pythagoras
  224.       dX            = newX - eyeX;             // Horizontal distance to move
  225.       dY            = newY - eyeY;             // Vertical distance to move
  226.       gazeFrames    = random(3, 15);           // Duration of eye movement
  227.       gazeCountdown = random(gazeFrames, 120); // Count to end of next movement
  228.     }
  229.   } else {
  230.     // Not in motion yet -- draw pupil at current static position
  231.     matrix[MATRIX_EYES].fillRect(eyeX, eyeY, 2, 2, LED_OFF);
  232.   }
  233.   // Scan buttons 6, 7, 8 looking for first button pressed...
  234.   for(i=0; (i<3) && (digitalRead(i+6) == HIGH); i++);
  235.   if(i < 3) {               // Anything pressed?  Yes!
  236.     if(i == prevBtn) {      // Same as last time we checked?  Good!
  237.       if(++btnCount == 3) { // 3 passes to 'debounce' button input
  238.         playfile((char *)pgm_read_word(&wavname[i])); // Start WAV
  239.         // Look up animation sequence # corresponding to this WAV...
  240.         seq            = (uint8_t *)pgm_read_word(&anim[i]);
  241.         idx            = 0; // Begin at first byte of data
  242.         newPos         = pgm_read_byte(&seq[idx++]); // Initial mouth pos
  243.         mouthCountdown = pgm_read_byte(&seq[idx++]); // Hold time for pos
  244.       }
  245.     } else btnCount = 0; // Different button than before - start count over
  246.     prevBtn = i;
  247.   } else prevBtn = 99;   // No buttons pressed
  248.   if(newPos != 255) { // Is the mouth in motion?
  249.     if(--mouthCountdown == 0) { // Count down frames to next position
  250.       newPos = pgm_read_byte(&seq[idx++]); // New mouth position
  251.       if(newPos == 255) { // End of list?
  252.         mouthPos = 0;     // Yes, set mouth to neutral position
  253.       } else {
  254.         mouthPos       = newPos; // Set mouth to new position
  255.         mouthCountdown = pgm_read_byte(&seq[idx++]); // Read hold time
  256.       }
  257.     }
  258.   } else mouthPos = 0; // Mouth not in motion -- set to neutral position
  259.   drawMouth(mouthImg[mouthPos]);
  260.   // Refresh all matrices in one quick pass
  261.   for(uint8_t i=0; i<4; i++) matrix[i].writeDisplay();
  262.   delay(20);
  263. }
  264. // Draw mouth image across three adjacent displays
  265. void drawMouth(const uint8_t *img) {
  266.   for(uint8_t i=0; i<3; i++) {
  267.     matrix[MATRIX_MOUTH_LEFT + i].clear();
  268.     matrix[MATRIX_MOUTH_LEFT + i].drawBitmap(i * -8, 0, img, 24, 8, LED_ON);
  269.   }
  270. }
  271. // Open and start playing a WAV file
  272. void playfile(const char *name) {
  273.   char filename[13]; // 8.3+NUL
  274.   if(wave.isplaying) wave.stop(); // Stop any currently-playing WAV
  275.   strcpy_P(filename, name); // Copy name out of PROGMEM into RAM
  276.   if(!file.open(root, filename)) {
  277.     Serial.print(F("Couldn't open file "));
  278.     Serial.println(filename);
  279.     return;
  280.   }
  281.   if(!wave.create(file)) {
  282.     Serial.println(F("Not a valid WAV"));
  283.     return;
  284.   }
  285.   wave.play();
  286. }
复制代码


回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-10 10:51:02

  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  项目之八:右向流动显示“SOS Call 9-1-1”

  实验开源代码

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  4.   项目之八:右向流动显示“SOS Call 9-1-1”
  5.   实验接线:
  6.   VK16k33    UNO
  7.   VIN        5V
  8.   GND        GND
  9.   SCL        A5
  10.   SDA        A4
  11. */
  12. #include <Wire.h>
  13. #include <Adafruit_GFX.h>
  14. #include "Adafruit_LEDBackpack.h"   //necessary
  15. Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
  16. void setup() {
  17.    
  18.   matrix.begin(0x70);  // pass in the address
  19. }
  20. static const uint8_t PROGMEM    // Setting Static Constants for the LED Matrix
  21.   S_bmp[] =                    // Declaring the "S" Shape Bitmap for the Matrix
  22.   { B01111111,                // String of characters dictates each LED position as on or off on 8x8 gird
  23.     B01111111,               // 0 = Off LED 1 = On LED  
  24.     B01100000,
  25.     B01111110,
  26.     B01111110,
  27.     B00000110,
  28.     B11111110,
  29.     B11111110 },
  30.    
  31.   O_bmp[] =               // Declaring the "O" Shape Bitmap for the Matrix
  32.   { B11111111,
  33.     B11111111,
  34.     B11000011,
  35.     B11000011,
  36.     B11000011,
  37.     B11000011,
  38.     B11111111,
  39.     B11111111 },
  40.    
  41.   S2_bmp[] =          // Declaring the second "S" Shape Bitmap for the Matrix
  42.   
  43.   { B01111111,
  44.     B01111111,
  45.     B01110000,
  46.     B01111110,
  47.     B01111110,
  48.     B00000110,
  49.     B11111110,
  50.     B11111110 };
  51. void loop() {
  52.   matrix.clear();                                     // Starting with clear matrix where all LEDs are off
  53.   matrix.drawBitmap(1, 0, S_bmp, 8, 8, LED_ON);      // Drawing the "S" Bitmap according to void setup configuration
  54.   matrix.writeDisplay();                            // With 2000 milisecond delay
  55.   delay(2000);
  56.   matrix.clear();                                    // Transitioning with clear matrix where all LEDs are off
  57.   matrix.drawBitmap(1, 0, O_bmp, 7, 8, LED_ON);     // Drawing the "O" Bitmap according to void setup configuration
  58.   matrix.writeDisplay();                           // With 2000 milisecond delay
  59.   delay(2000);
  60.   matrix.clear();                                    // Transitioning with clear matrix where all LEDs are off
  61.   matrix.drawBitmap(1, 0, S2_bmp, 7, 8, LED_ON);    // Drawing the second "S" Bitmap according to void setup configuration
  62.   matrix.writeDisplay();                           // With 2000 milisecond delay
  63.   delay(2000);
  64.   matrix.setTextSize(1);                          // Setting matrix text size to 1
  65.   matrix.setTextWrap(false);                     // Preventing text wrapping to scroll text continuously through matrix
  66.   matrix.setTextColor(LED_ON);                  // Turning LED On
  67.   for (int8_t x=0; x>=-36; x--) {              // Setting for loop to position letters side by side for the scroll
  68.     matrix.clear();                           // Transitioning with clear matrix where all LEDs are off
  69.     matrix.setCursor(x,0);                   // Defining letter positions to print one at time side by side
  70.     matrix.print(" Call");                   // Printing "Call" on the matrix
  71.     matrix.writeDisplay();                 // With 100 milisecond delay
  72.     delay(100);
  73.   }
  74.   matrix.setRotation(0);                  // Prevent rotation and keep scroll at the same angle
  75.   for (int8_t x=7; x>=-36; x--) {        // Setting new for loop to position letters side by side for the scroll
  76.     matrix.clear();                     // Transitioning with clear matrix where all LEDs are off
  77.     matrix.setCursor(x,0);             // Defining letter positions to print one at time side by side
  78.     matrix.print("9-1-1");            // Printing "9-1-1" on the matrix
  79.     matrix.writeDisplay();           // With 100 milisecond delay
  80.     delay(100);
  81.   }
  82. }
复制代码


回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 10:02:48

Arduino 系列传感器和执行器模块实验目录清单:
一块扩展板完成Arduino的10类37项实验(代码+图形+仿真)
https://mc.dfrobot.com.cn/thread-280845-1-1.html
连杆形式的腿机构十一种:盘点机器人行走背后的机械原理
https://mc.dfrobot.com.cn/thread-308097-1-1.html
【花雕动手做】超低成本,尝试五十元的麦克纳姆轮小车!
https://mc.dfrobot.com.cn/thread-307863-1-1.html
【花雕动手做】超迷你哦,用徽商香烟盒做个智能小车!
https://mc.dfrobot.com.cn/thread-307907-1-1.html
【花雕动手做】太搞笑啦,一支胶管制成二只蠕动机器人
https://mc.dfrobot.com.cn/thread-308046-1-1.html
【花雕动手做】快餐盒盖,极低成本搭建机器人实验平台
https://mc.dfrobot.com.cn/thread-308063-1-1.html
【花雕动手做】特别苗条,使用微波传感器控制的纤细小车
https://mc.dfrobot.com.cn/thread-308866-1-1.html
【花雕动手做】脑洞大开、五花八门的简易机器人66种
https://mc.dfrobot.com.cn/thread-307900-1-1.html

实验一百五十八:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
https://mc.dfrobot.com.cn/thread-308195-1-1.html
实验一百六十三:BMI160 6轴惯性运动传感器 16位3轴加速度+超低功耗3轴陀螺仪  I2C/SPI 14LGA
https://mc.dfrobot.com.cn/thread-310371-1-1.html
实验一百六十五:2.4 英寸 TFT LCD 触摸屏模块 XPT2046 PCB ILI9341 240x320 像素 8 位 SPI 串口显示器 300mA
https://mc.dfrobot.com.cn/thread-309803-1-1.html
实验一百七十六:6mm大尺寸8x8LED方块方格点阵模块 可级联 红绿蓝白色 可选8级亮度
https://mc.dfrobot.com.cn/thread-309845-1-1.html
实验一百八十三:GY-530 VL53L0X 激光测距 ToF测距 飞行时间测距传感器模块 IIC通信协议
https://mc.dfrobot.com.cn/thread-310273-1-1.html
实验一百八十五:MAX4466声音传感器 驻极体话筒放大器 麦克风可调功放模块 microphone
https://mc.dfrobot.com.cn/thread-310193-1-1.html
实验一百八十九:TDA1308 硅麦克风 数字咪头放大模块 拾音器放大板 楼氏SUNLEPHANT
https://mc.dfrobot.com.cn/thread-310246-1-1.html
实验一百九十三:TCS34725颜色识别传感器 RGB IIC明光感应模块 ColorSensor
https://mc.dfrobot.com.cn/thread-310209-1-1.html
实验二百:RCWL-0515微波雷达感应开关 人体感应 智能感应探测传感器 12-15米远距离2.7G微波检测模块
https://mc.dfrobot.com.cn/thread-310313-1-1.html
实验二百零三:Air724UG合宙 Cat14G模块 DTU物联网UART串口通信数据TCP透传 核心板组合套餐
https://mc.dfrobot.com.cn/thread-310342-1-1.html
实验二百零七:I2C红色8*8LED点阵模块ht16k33驱动1088BS树莓派物联网可扩展编程
https://mc.dfrobot.com.cn/thread-310951-1-1.html
实验二百零九:Gravity: I2C & UART BC20 NB-IoT & GNSS通信模块 NB-IoT广域低功耗无线通信 GPS/北斗精准定位
https://mc.dfrobot.com.cn/thread-310433-1-1.html

回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 11:16:52

查看模块的驱动芯片

01.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 11:28:47

本帖最后由 驴友花雕 于 2021-9-9 12:55 编辑

02.jpg

VK16K33
是一款存储器映射和多功能LED控制驱动芯片。该芯片支持更大 128 点的显示模式(16SEGs×8COMs) 以及更大 13×3 的按键矩阵扫描电路。VK16K33 的软件配置特性使其适用于多种 LED 应用,包括 LED 模块和显示子系统。VK16K33 通过双向I2C 接口可与大多数微控制器进行通信。


功能特点1.工作电压:4.5V~5.5V2.内部 RC 振荡器3.I2C 总线接口4.16×8 位 RAM 用于存储显示数据5.更大显示模式为16×8:16SEGs和8COMs6.读 /写地址自动递增7.多达13×3 按键矩阵扫描功能8. 16阶调光电路9.封装类型:20/24/28-pin SOP    VK16K33此系列IC具有低功耗、高抗杂讯及高系统ESD防护能力;VK16K33整合了LED驱动和按键扫描的功能,将控制面板所需要的功能融合于一身,可降低主MCU的负担及需要的I/O数目。采用I2C的介面更可减少控制面板和主板之间的材料成本、进而降低产品整体成本。


VK16K33有28SOP、24SOP和20SOP三种包装,分别对应三种更大显示点数;16x8点LED和13x3个按键、12x8点LED和10x3个按键,以及8x8点LED和8x3个按键。内建显示记忆体及RC振荡电路;工作电压:4.5V~5.5V;VK16K33支持中断信号和轮询两种工作模式。可选择性的提供按键中断信号给MCU,MCU可不须一直检查按键状态。VK16K33与系统控制晶片的传输只需2根信号线,通过VK16K33 侦测按键输入,可减少主版MCU I/O数目及精简主版及面板的布局线路;因此可降低产品整体成本。 VK16K33适用于家电、影音设备、仪表设备、车用装置等LED显示器/面板的控制及驱动。
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 11:50:33

VK16K33参数特点
工作电压:4.5V-5.5V
集成RC振荡器
I2C总线接口
16×8位RAM用于显示数据存储
最高 16×8模式,16段和8个共同点
读/写地址自动递增
最高 13×3矩阵键扫描
16级调光电路
20/24/28引脚SOP封装类型

VK16K33主要应用
工控指标
数字时钟、温度计、计数器、万用表
组合套装
录像机
仪表读数
其他消费类应用
LED显示屏

02-2.jpg

回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 12:20:28

VK16K33功能框图

02-3.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 12:26:47

VK16K33近似内部连接图

02-6.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 12:28:28

VK16K33管脚

02-4.jpg

回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 12:30:14

回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 13:08:48

1088BS共阳点阵屏


03-2.jpg

03-1.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 13:10:29

03.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 13:17:19

04.jpg

I2C88单色点阵模块,采用HT16K33芯片作为驱动,可以仅仅使用2个IO管脚就能驱动点亮 I2C点阵模块,可以与Arduino或者其他单片机级联使用。

电源要求:+4.5-5.5V
输入类型:数字信号
接口模式:XH2.54×4
引脚定义:G-地  V-电源   D(SDA)-串行数据  C(SCL)-串行时钟
模块重量:35g

回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 14:55:17

I2C红色8*8LED点阵模块VK16k33驱动,参考电原理图


02-1.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 14:59:34

连线方法:按照传感器模块接口标号与主控制器相连接,标号“G”接主控制器的“地”、“V”接“电源”、“D”接“Arduino UNO R3”SDA,“C”接“Arduino UNO R3”SCL

05-.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 15:01:25

05.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 15:02:33

04-.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 16:38:05

本帖最后由 驴友花雕 于 2021-9-9 17:46 编辑

  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  项目之一:8x8 LED 矩阵测试,显示一个点

  实验开源代码
  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  4.   项目之一:8x8 LED 矩阵测试,显示一个点
  5.   实验接线:
  6.   VK16k33    UNO
  7.   VIN        5V
  8.   GND        GND
  9.   SCL        A5
  10.   SDA        A4
  11. */
  12. // For I2C
  13. #include <Wire.h>
  14. // Libraries for Matrix
  15. #include "Adafruit_LEDBackpack.h"
  16. #include "Adafruit_GFX.h"
  17. Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
  18. void setup() {
  19.   Serial.begin(9600);
  20.   // Good idea to send data to both
  21.   // device and serial as it helps with
  22.   // troubleshooting.
  23.   Serial.println("8x8 LED 矩阵测试");
  24.   // set the address
  25.   matrix.begin(0x70);
  26. }
  27. void loop() {
  28.   // clear display
  29.   matrix.clear();
  30.   // set pixel x,y to ON
  31.   matrix.drawPixel(0, 0, LED_ON);
  32.   // write RAM to matrix
  33.   matrix.writeDisplay();
  34.   delay(500);
  35. }
复制代码


回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 16:39:28

本帖最后由 驴友花雕 于 2021-9-9 17:49 编辑

实验串口返回情况

06-.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 16:41:10

本帖最后由 驴友花雕 于 2021-9-9 17:51 编辑

实验场景图

07-.jpg
回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 16:58:55

  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  项目之二:流水瀑布,循环显示

  实验开源代码

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百零七:I2C红色8*8LED点阵模块VK16k33驱动1088BS树莓派物联网可扩展编程
  4.   项目之二:流水瀑布,循环显示
  5.   实验接线:
  6.   VK16k33    UNO
  7.   VIN        5V
  8.   GND        GND
  9.   SCL        A5
  10.   SDA        A4
  11. */
  12. // 引用I2C库
  13. #include <Wire.h>
  14. // 引用ht16k33库
  15. #include "ht16k33.h"
  16. // LED Matrix 模块默认地址为:0x70
  17. #define I2C_ADDR 0x70
  18. HT16K33 *led = NULL;  // 申明模块变量
  19. void setup() {
  20.   // 初始化I2C, 也可以使用TwoWire
  21.   Wire.begin();
  22.   // 初始化串口
  23.   Serial.begin(115200);
  24.   while (led == NULL) {
  25.     // 当led没有实例化,就循环检测模块是否连接
  26.     Wire.beginTransmission(I2C_ADDR);
  27.     uint8_t error = Wire.endTransmission();
  28.     if (error == 0) {
  29.       Serial.print("LED Matrix module is found at address 0x");
  30.       Serial.println(I2C_ADDR, HEX);
  31.       led = new HT16K33(I2C_ADDR);
  32.     }
  33.     delay(2000);
  34.   }
  35.   // 打开模块
  36.   led->displayOn();
  37. }
  38. void loop() {
  39.   if (led != NULL) {
  40.     // 清除模块所有显示
  41.     led->clear();
  42.     // 每次需要刷新模块显示,都需要调用write方法将数据传递给模块
  43.     led->write();
  44.     // 瀑布demo
  45.     for (int i = 0; i < 8; i++) {
  46.       for (int j = 0; j < 8; j++) {
  47.         led->setPixel(i, j, 1);
  48.         led->write();
  49.         delay(30);
  50.       }
  51.     }
  52.   }
  53.   delay(2000);
  54. }
复制代码


回复

使用道具 举报

驴友花雕  初级技神
 楼主|

发表于 2021-9-9 17:06:03

实验场景图  动态图   WeChat_20210909170311.gif
回复

使用道具 举报

123下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2022 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail