Advertisement
ripred

DS1882.ino

Jun 2nd, 2023 (edited)
615
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.06 KB | Source Code | 0 0
  1. // --------------------------------------
  2. // Example use of the DS1882 Dual Channel Digital Potentiometer
  3. //
  4. // 2021 ++trent m. wyatt
  5. //
  6. #include <Arduino.h>
  7. #include <Printf.h>
  8. #include <Wire.h>
  9.  
  10. #define   DIGIPOT_ADDR   0x28
  11.  
  12.  
  13. // Command byte upper 2 bits determines command:
  14. //                    Config          Register
  15. //                   Selection        Settings
  16. //                     0b00            xxxxxx
  17. //        Invalid      0b11xxxxxx
  18. #define   WRITE_POT0   0b00000000
  19. #define   WRITE_POT1   0b01000000
  20. #define   WRITE_CFG    0b10000000
  21.  
  22. // Config Register, lower 3 bits:
  23. // Volatile/Nonvolatile Potentiometer Register Control Bit: A control bit that sets the
  24. //   potentiometer registers to be either volatile or nonvolatile memory.
  25. // 0 = Potentiometer registers are set to nonvolatile memory storage.
  26. // 1 = Potentiometer registers are set to volatile memory storage. On power-up, the potentiometer wipers are in the mute position (default).
  27. #define   NONVOLATILE  0b00000100
  28.  
  29. // Zero-Crossing Detection Enable Bit: A bit used to enable and disable the zero-crossing functionality.
  30. // 0 = Zero-crossing detection is disabled.
  31. // 1 = Zero-crossing detection is enabled (default).
  32. #define   ZEROCROSSING 0b00000010
  33.  
  34. // Potentiometer Position Configuration: A control bit used to select the number of positions both potentiometers have.
  35. // 0 = Potentiometers have 63 positions and mute.
  36. // 1 = Potentiometers have 33 positions and mute (default).
  37. #define   POTCONFIG    0b00000001
  38.  
  39. uint8_t  cfg_value = NONVOLATILE | ZEROCROSSING | POTCONFIG;
  40. int8_t  pot0_value = 0;
  41. int8_t  pot1_value = 0;
  42. uint8_t  which_pot = 0;
  43.  
  44. enum Modes { InvalidMode = -1, MenuMode, ScanMode, Tremelo };
  45.  
  46. Modes mode = InvalidMode;
  47.  
  48. void update_values() {
  49.     write_config(cfg_value);
  50.     write_pot0(pot0_value);
  51.     write_pot1(pot1_value);
  52.     //display_status();
  53. }
  54.  
  55.  
  56. void setup() {
  57.     mode = MenuMode;
  58. //    mode = ScanMode;
  59. //    mode = Tremelo;
  60.  
  61.     digitalWrite(5, HIGH);
  62.     pinMode(5, OUTPUT);
  63.  
  64.     digitalWrite(LED_BUILTIN, LOW);
  65.     pinMode(LED_BUILTIN, OUTPUT);
  66.  
  67.     Wire.begin();
  68.  
  69.     //Serial.begin(230400);
  70.     Serial.begin(2000000);
  71.     delayMicroseconds(10);
  72.     while (!Serial); // Leonardo: wait for Serial Monitor
  73.     printf("\n");
  74.  
  75.     if (ScanMode == mode) {
  76.         printf("\nI2C Scanner\n");
  77.     }
  78.  
  79.     display_status();
  80. }
  81.  
  82. void display_status() {
  83.     printf("Selected potentiometer: ");
  84.     if (2 == which_pot) {
  85.         printf("Both\n");
  86.     }
  87.     else {
  88.         printf("%d\n", which_pot);
  89.     }
  90.     printf("(V) Non-volatile is set to %s\n", (cfg_value & NONVOLATILE) == 0 ? "false" : "true");
  91.     printf("(Z) Zero-crossing is set to %s\n", (cfg_value & ZEROCROSSING) == 0 ? "false" : "true");
  92.     printf("(C) Pot-config is set to %s\n", (cfg_value & POTCONFIG) == 0 ? "Option 0" : "Option 1");
  93.     printf("(0) Pot 0 value = %d\n", pot0_value);
  94.     printf("(1) Pot 1 value = %d\n", pot1_value);
  95.     printf("\n");
  96. }
  97.  
  98.  
  99. int factor0 = 1;
  100. int factor1 = 1;
  101.  
  102. void loop() {
  103.     static unsigned long timer = millis() + 1000UL;
  104.     if (millis() >= timer) {
  105.         timer = millis() + 1000UL;
  106.         digitalWrite(LED_BUILTIN, !
  107.         digitalRead(LED_BUILTIN));
  108.     }
  109.  
  110.     unsigned long dur = 100000000UL;
  111.  
  112.     switch (mode) {
  113.         case Tremelo:
  114.             pot0_value += factor0;
  115.             if (pot0_value < 10 || pot0_value >= 20)
  116.                 factor0 *= -1;
  117.             pot1_value += factor1;
  118.             if (pot1_value < 10 || pot1_value >= 20)
  119.                 factor1 *= -1;
  120.             update_values();
  121.             delayMicroseconds(dur);
  122.             break;
  123.  
  124.         case MenuMode:
  125.             menuloop();
  126.             break;
  127.  
  128.         case ScanMode:
  129.             scanloop();
  130.             break;
  131.  
  132.         default:
  133.             printf("Invalid mode: %d.\nStopping.\n", mode);
  134.             while (true) { ; }
  135.             break;
  136.     }
  137. }
  138.  
  139.  
  140. void menuloop() {
  141.     if (Serial.available() > 0) {
  142.         while (Serial.available() > 0) {
  143.             uint8_t b = Serial.read();
  144.             b = toupper(b);
  145.             if (isdigit(b) || isalpha(b)) {
  146.                 switch (b) {
  147.                     case '0':
  148.                         printf("Switching to potentiometer 0\n");
  149.                         which_pot = 0;
  150.                         break;
  151.  
  152.                     case '1':
  153.                         printf("Switching to potentiometer 1\n");
  154.                         which_pot = 1;
  155.                         break;
  156.  
  157.                     case '2':
  158.                         printf("Switching to both potentiometers\n");
  159.                         which_pot = 2;
  160.                         break;
  161.  
  162.                     case 'V':
  163.                         cfg_value ^= NONVOLATILE;
  164.                         printf("Switching non-volatile to %s\n", (cfg_value & NONVOLATILE) == 0 ? "false" : "true");
  165.                         break;
  166.  
  167.                     case 'Z':
  168.                         cfg_value ^= ZEROCROSSING;
  169.                         printf("Switching zero-crossing to %s\n", (cfg_value & ZEROCROSSING) == 0 ? "false" : "true");
  170.                         break;
  171.  
  172.                     case 'C':
  173.                         cfg_value ^= POTCONFIG;
  174.                         printf("Switching pot-config to %s\n", (cfg_value & POTCONFIG) == 0 ? "Option 0" : "Option 1");
  175.                         break;
  176.  
  177.                     case 'U':
  178.                         if (0 == which_pot || 2 == which_pot) {
  179.                             pot0_value++;
  180.                             printf("Up. Pot 0 value = %d\n", pot0_value);
  181.                         }
  182.                         if (1 == which_pot || 2 == which_pot) {
  183.                             pot1_value++;
  184.                             printf("Up. Pot 1 value = %d\n", pot1_value);
  185.                         }
  186.                         update_values();
  187.                         break;
  188.  
  189.                     case 'D':
  190.                         if (0 == which_pot || 2 == which_pot) {
  191.                             pot0_value--;
  192.                             if (pot0_value < 0) pot0_value = 0;
  193.                             printf("Down. Pot 0 value = %d\n", pot0_value);
  194.                         }
  195.                         if (1 == which_pot || 2 == which_pot) {
  196.                             pot1_value--;
  197.                             if (pot1_value < 0) pot1_value = 0;
  198.                             printf("Down. Pot 1 value = %d\n", pot1_value);
  199.                         }
  200.                         update_values();
  201.                         break;
  202.  
  203.                     default:
  204.                         break;
  205.                 }
  206.             }
  207.         }
  208.         display_status();
  209.     }
  210. }
  211.  
  212. uint8_t write_pot0(uint8_t b) {
  213.     return sendSingle(WRITE_POT0 | (b & 0x3F));
  214. }
  215.  
  216. uint8_t write_pot1(uint8_t b) {
  217.     return sendSingle(WRITE_POT1 | (b & 0x3F));
  218. }
  219.  
  220. uint8_t write_config(uint8_t b) {
  221.     return sendSingle(WRITE_CFG | (b & 0x3F));
  222. }
  223.  
  224. uint8_t sendSingle(uint8_t b1) {
  225.     digitalWrite(5, LOW);
  226.     delay(1);
  227.     Wire.beginTransmission(DIGIPOT_ADDR);
  228.     Wire.write(b1);
  229.     uint8_t error = Wire.endTransmission();
  230.     delay(1);
  231.     digitalWrite(5, HIGH);
  232.  
  233.     return error;
  234. }
  235.  
  236. void scanloop() {
  237.   static int Pass = 1;
  238.   int nDevices = 0;
  239.  
  240.   printf("Scanning pass #%d...\n", Pass++);
  241.   digitalWrite(LED_BUILTIN, HIGH);
  242.  
  243.   for (byte address = 1; address < 127; ++address) {
  244.     // The i2c_scanner uses the return value of
  245.     // the Wire.endTransmission to see if
  246.     // a device did acknowledge to the address.
  247.     digitalWrite(5, LOW);
  248.     delay(1);
  249.     Wire.beginTransmission(address);
  250.     byte error = Wire.endTransmission();
  251.     delay(1);
  252.     digitalWrite(5, HIGH);
  253.  
  254.     if (0 == error ) {
  255.       printf("I2C device found at address 0x%02X  !\n", address);
  256.       ++nDevices;
  257.     } else if (error == 4) {
  258.       printf("Unknown error at address 0x%02X\n", address);
  259.     }
  260.   }
  261.   digitalWrite(LED_BUILTIN, LOW);
  262.  
  263.   if (nDevices == 0) {
  264.     printf("No I2C devices found\n\n");
  265.   } else {
  266.     printf("%d devices found. Done\n\n", nDevices);
  267.   }
  268.   delay(5000); // Wait 5 seconds for next scan
  269. }
  270.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement