Announcement

Collapse
No announcement yet.

Jazzing up the Arduino PI - full recipe

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Originally posted by Gunghouk View Post
    Correction:

    delayVal = round(map(analogRead(delayPin), 0, 1023, defMainDelay, defMaxDelay)); // new delay value

    Do you realize you're rounding integers?

    long is an integer type and a division of integers in C, C++ is also an integer, not a float.

    Comment


    • #17
      I think truncating the MAP output instead of rounding gives approx equal pot rotation angle per uS

      delayVal = trunc(map(analogRead(delayPin), 0, 1023, defMainDelay, defMaxDelay)); // new delay value

      Comment


      • #18
        Originally posted by Teleno View Post
        Do you realize you're rounding integers?

        long is an integer type and a division of integers in C, C++ is also an integer, not a float.
        Erm.....looking at the Arduino reference for MAP and my Excel sheet shows fractions........

        My bad again

        Comment


        • #19
          Originally posted by Gunghouk View Post
          Correction:

          delayVal = round(map(analogRead(delayPin), 0, 1023, defMainDelay, defMaxDelay)); // new delay value

          Check this out this simulation https://onlinegdb.com/fyy3Uo5KI

          PHP Code:
          #include <stdlib.h>
          #include <stdio.h>
          #include <math.h>

          #define defMainDelay 5
          #define defMaxDelay 16

          long delayVal;
          long lastDelayVal = -1;
          long noisyDelayVal;

          long map(long xlong in_minlong in_maxlong out_minlong out_max)
          {
          return (
          in_min) * (out_max out_min) / (in_max in_min) + out_min;
          }


          int main() {

              
              
          // swipe all  pot values
              
          for (long analogRead 2analogRead 1024analogRead++){
                  
                  
          // noiseless delayVal update
                  
          delayVal round(map(analogRead01023defMainDelaydefMaxDelay));
                  if (
          delayVal lastDelayVal){
                      
          printf("current delayVal is %ld\n"delayVal);
                      
          lastDelayVal delayVal;
                  }
                  
                  
          // subtract 1 bit of noise
                  
          long noisyAnalogRead analogRead 1;
                  
          noisyDelayVal round(map(noisyAnalogRead01023defMainDelaydefMaxDelay));
                  
                  
          // if there's flicker the mapped value will be less than the noiseless value.
                  
          if (noisyDelayVal delayVal){
                      
          printf("%ld %ld %s\n"analogReadnoisyDelayVal"<- flicker");
                  }

                  
          // add 1 bit of noise
                  
          noisyAnalogRead analogRead 1;
                  
          noisyDelayVal round(map(noisyAnalogRead01023defMainDelaydefMaxDelay));
                  
                  
          // if there's flicker the mapped value will be more than the noiseless value.
                  
          if (noisyDelayVal delayVal){
                      
          printf("%ld %ld %s\n"analogReadnoisyDelayVal"<- flicker");
                  }
              }
              
              return 
          0;
          }

          ​ 




          It only adds +- 1 bit of noise, it would be much worse in real life.

          output:
          Code:
          current delayVal is 5
          92 6 <- flicker
          current delayVal is 6
          93 5 <- flicker
          185 7 <- flicker
          current delayVal is 7
          186 6 <- flicker
          278 8 <- flicker
          current delayVal is 8
          279 7 <- flicker
          371 9 <- flicker
          current delayVal is 9
          372 8 <- flicker
          464 10 <- flicker
          current delayVal is 10
          465 9 <- flicker
          557 11 <- flicker
          current delayVal is 11
          558 10 <- flicker
          650 12 <- flicker
          current delayVal is 12
          651 11 <- flicker
          743 13 <- flicker
          current delayVal is 13
          744 12 <- flicker
          836 14 <- flicker
          current delayVal is 14
          837 13 <- flicker
          929 15 <- flicker
          current delayVal is 15
          930 14 <- flicker
          1022 16 <- flicker
          current delayVal is 16
          1023 15 <- flicker​

          Comment


          • #20
            Now the same wiith +-1 bit of noise and +-1 bit hysteresis.

            https://onlinegdb.com/wyqRfLz6M

            PHP Code:
            #include <stdlib.h>
            #include <stdio.h>
            #include <math.h>

            #define defMainDelay 5
            #define defMaxDelay 16

            long delayVal;
            long lastDelayVal = -1;
            long noisyDelayVal;

            long threshold_upthreshold_down 0;

            long map(long xlong in_minlong in_maxlong out_minlong out_max)
            {
            return (
            in_min) * (out_max out_min) / (in_max in_min) + out_min;
            }


            int hysteresis(long analog){
                
            int accept 11;
                
            int reject 0;
                
                if(
            analog threshold_up || analog threshold_down){
                  
            threshold_up = (analog 1024)? analog 1024;
                  
            threshold_down = (analog 0)? analog 0;
                  return 
            accept;
                }
                else return 
            reject;
            }


            int main() {

                
                
            // swipe all  pot values
                
            for (long analogRead 2analogRead 1024analogRead++){
                    
                    
            // noiseless delayVal update
                    
            delayVal round(map(analogRead01023defMainDelaydefMaxDelay));
                    if (
            delayVal lastDelayVal){
                        
            printf("current delayVal is %ld\n"delayVal);
                        
            lastDelayVal delayVal;
                    }
                    
                    
            // subtract 1 bit of noise
                    
            long noisyAnalogRead analogRead 1;
                    if(
            hysteresis(noisyAnalogRead) == 1) {
                        
            noisyDelayVal round(map(noisyAnalogRead01023defMainDelaydefMaxDelay));
                        
                        
            // if there's flicker the mapped value will be less than the noiseless value.
                        
            if (noisyDelayVal delayVal){
                            
            printf("%ld %ld %s\n"analogReadnoisyDelayVal"<- flicker");
                        }
                    }

                    
            // add 1 bit of noise
                    
            noisyAnalogRead analogRead 1;
                    if(
            hysteresis(noisyAnalogRead) == 1) {
                        
            noisyDelayVal round(map(noisyAnalogRead01023defMainDelaydefMaxDelay));
                        
                        
            // if there's flicker the mapped value will be more than the noiseless value.
                        
            if (noisyDelayVal delayVal){
                            
            printf("%ld %ld %s\n"analogReadnoisyDelayVal"<- flicker");
                        }
                    }
                }
                
                return 
            0;
            }

            ​ 


            Output

            Code:
            current delayVal is 5
            current delayVal is 6
            current delayVal is 7
            current delayVal is 8
            current delayVal is 9
            current delayVal is 10
            current delayVal is 11
            current delayVal is 12
            current delayVal is 13
            current delayVal is 14
            current delayVal is 15
            current delayVal is 16​

            Comment


            • #21
              Thank you for your patience and for taking the time to point out my misconceptions

              Comment


              • #22
                Originally posted by Gunghouk View Post
                Thank you for your patience and for taking the time to point out my misconceptions
                No problem. I want to make sure the code is solid so I had to do the simulations.

                On the bench you can notice the hysyeresis on the pot. Once you set a delay it takes an additional displacement to go back to the previous value and another to return to the current delay.

                So here's the new version with stable pot.

                Version 1.0.3

                ArduinoPI_fullPWM_1_0_3.zip

                Changes in 1.0.3:

                - Pot reading validated against adaptive hysteresis thresholds before being accepted (+- 8 bit noise).​
                Attached Files

                Comment


                • #23
                  Nice....... erm life would be so much easier with an encoder

                  Toggle power with the encoder button and set delay with the encoder. I've plans to show the TX power in the bottom left of the oled.

                  TXlo or TXhi

                  Comment


                  • #24
                    Originally posted by Gunghouk View Post
                    Nice....... erm life would be so much easier with an encoder

                    Toggle power with the encoder button and set delay with the encoder. I've plans to show the TX power in the bottom left of the oled.

                    TXlo or TXhi
                    Version 1.0.4

                    Changes in 1.0.4:

                    - TX Boost icon added to the FontLargeDigits.h file.Code for displaying it on switch changes.​


                    ArduinoPI_fullPWM_1_0_4.zip


                    Attached Files

                    Comment


                    • #25

                      Comment


                      • #26
                        For those willing to try the LGT8F328P based Nano there are two Arduino cores you can install:

                        https://github.com/dbuezas/lgt8fx
                        https://github.com/nulllaborg/arduino_nulllab

                        For compatibility with the OLED library, edit the "Arduino.h" of any of the above cores and delete or comment out these lines at the bottom of the file:

                        PHP Code:
                        /* deleted for compatibility with the OLED library Tiny4kOLED
                        #ifndef nop
                        #define    nop()    __asm__ __volatile__ ("nop" ::)
                        #endif
                        */
                        ​ 

                        Comment


                        • #27
                          Version 1.0.5

                          Changes in 1.0.5:
                          - Added low-pass IIR filter for the pot reading, reducing noise substantially. Less hysteresis is necessary, allowing a larger delay range.
                          This requires a higer refresh rate for the pot, so it's now read 1000 per second.

                          ArduinoPI_fullPWM_1_0_5.zip

                          I want to point out that I believe C6 and R13 between TP6 and the input of the analog switches are totally wrong.

                          C6/R13 turn the EF signal (which is constant within one period) into a decaying exponential. After efeSampleDelay the signal being subtracted at the differential integrator is not the EF signal level that's riding on the main sample, but a decayed version at a lower level, breaking the EF compensation scheme.

                          In MOD3 (see /doc folder in the sketch distribution) I suggest removing C6 and shorting its pads, and removing R13. Then adjust the offset at TP6.​
                          Attached Files

                          Comment


                          • #28
                            I thought this was an elegant running average solution used in George's Voodoo Project. I've put the call in the main loop. I have averaging count set to 64.

                            if (readPot) {
                            // IIR low pass filter
                            //potReading = analogRead(delayPin);

                            getPotReading(); // running average filter
                            readPot = false;

                            // update audio frequency.
                            #ifdef USE_FREQ_MODULATION
                            word target = analogRead(targetPin);
                            freq = map(target, 0, 635, FREQ_MIN, FREQ_MAX);
                            freq = constrain(freq, FREQ_MIN, FREQ_MAX);
                            OCR2A = TIMER2_CLK / freq - 1;
                            #endif
                            }


                            unsigned int getPotReading()
                            {
                            potReading = analogRead(delayPin); // Acquire reading
                            averagingTotal -= averagingArray[averagingIndex]; // Remove oldest reading from the total
                            averagingTotal += potReading; // Add latest reading to the total
                            averagingArray[averagingIndex] = potReading; // Add latest reading to pot averaging array
                            potReading = averagingTotal/averagingCount; // Average readings

                            if(++averagingIndex >= averagingCount) // Increment PI index
                            averagingIndex = 0; // Wrap if needed

                            return potReading;
                            }​

                            Comment


                            • #29
                              Originally posted by Gunghouk View Post
                              I thought this was an elegant running average solution used in George's Voodoo Project. I've put the call in the main loop. I have averaging count set to 64.

                              if (readPot) {
                              // IIR low pass filter
                              //potReading = analogRead(delayPin);

                              getPotReading(); // running average filter
                              readPot = false;

                              // update audio frequency.
                              #ifdef USE_FREQ_MODULATION
                              word target = analogRead(targetPin);
                              freq = map(target, 0, 635, FREQ_MIN, FREQ_MAX);
                              freq = constrain(freq, FREQ_MIN, FREQ_MAX);
                              OCR2A = TIMER2_CLK / freq - 1;
                              #endif
                              }


                              unsigned int getPotReading()
                              {
                              potReading = analogRead(delayPin); // Acquire reading
                              averagingTotal -= averagingArray[averagingIndex]; // Remove oldest reading from the total
                              averagingTotal += potReading; // Add latest reading to the total
                              averagingArray[averagingIndex] = potReading; // Add latest reading to pot averaging array
                              potReading = averagingTotal/averagingCount; // Average readings

                              if(++averagingIndex >= averagingCount) // Increment PI index
                              averagingIndex = 0; // Wrap if needed

                              return potReading;
                              }​
                              That's a lot more code and memory footprint than a simple low pass filter anyway.

                              Comment


                              • #30
                                Originally posted by Teleno View Post

                                That's a lot more code and memory footprint than a simple low pass filter anyway.
                                For the array for sure but there's plenty of memory available but as an alternative or efficient replacement for the IIR I can't say. I just like its compactness and understandibilty.

                                All moot if the pot is replaced with an encoder.

                                Comment

                                Working...