Trying to read button presses

Post here first, or if you can't find a relevant section!
User avatar
efftek
Posts: 80
Joined: Tue Jan 10, 2017 9:42 pm
Location: Πάφος, Cyprus
Contact:

Re: Trying to read button presses

Post by efftek » Tue Mar 21, 2017 8:32 pm

Nutsy wrote:Bearly functions as its designed too.
Sorry to be pedantic but its actually barely.

Unless the design function is to go "RARRRRRRRRRRRRRRRRR"

Please don't take offence, that was just a speeling mistake I couldn't let go. Lord knoes I make enough myself LOL

User avatar
efftek
Posts: 80
Joined: Tue Jan 10, 2017 9:42 pm
Location: Πάφος, Cyprus
Contact:

Re: Trying to read button presses

Post by efftek » Tue Mar 21, 2017 8:34 pm

efftek wrote:One butto turns the board LED on
See what I mean hehe

david.prentice
Posts: 113
Joined: Wed Nov 16, 2016 8:52 am

Re: Trying to read button presses

Post by david.prentice » Tue Mar 21, 2017 10:43 pm

You normally read button presses in a regular Timer interrupt. XOR the new reading with the previous reading to determine a change. Increment counter for a steady state. A button is effectively debounced when it has had a steady value for 20ms. A "long press" can be detected by a large count.

The button scan takes very few processing cycles. Most apps have a regular Timer interrupt anyway e.g. SYSCLOCK.

Your ADC will work in the background. An interrupt flag is set when the ADC completes.

David.

Nutsy
Posts: 255
Joined: Sun Jul 24, 2016 4:26 pm

Re: Trying to read button presses

Post by Nutsy » Wed Mar 22, 2017 11:14 am

I think if the nextion Rarred it would be an improvement :p

User avatar
efftek
Posts: 80
Joined: Tue Jan 10, 2017 9:42 pm
Location: Πάφος, Cyprus
Contact:

Re: Trying to read button presses

Post by efftek » Wed Mar 22, 2017 9:29 pm

david.prentice wrote:Your ADC will work in the background.
Not having a clue how to use the ADC properly, I use an if(micros()>= ... statement to apply an apropriate delay until i can read the next value from the ADC using the real = analogRead(PA0); statement until I have the required length array

And before anyone picks me up, I know real is not an array element, thats taken care of by the next line

x[a] = (((uint16_t)(real*16)) | ((uint32_t)(imag<<16)));

Steve.

Nutsy
Posts: 255
Joined: Sun Jul 24, 2016 4:26 pm

Re: Trying to read button presses

Post by Nutsy » Sun Mar 26, 2017 12:46 pm

efftek wrote:
david.prentice wrote:Your ADC will work in the background.
x[a] = (((uint16_t)(real*16)) | ((uint32_t)(imag<<16)));

Steve.
I dont know if its because im so tired... but i can barely understand what that line does :p

User avatar
efftek
Posts: 80
Joined: Tue Jan 10, 2017 9:42 pm
Location: Πάφος, Cyprus
Contact:

Re: Trying to read button presses

Post by efftek » Mon Mar 27, 2017 9:45 am

Nutsy wrote: I dont know if its because im so tired... but i can barely understand what that line does :p
I know the feeling

Here's the full code. Ive actually modified it since that post so it reads from two adc port and produces two fft's. That line is taking the 16 bit integer and shifting it into a 32 bit integer which contains a 16 bit real value (the one from the adc) and a 16 bit imaginary value (zero) which is the way the fft function needs its data to be stored.

Hope this explains it and get yourself a good nights sleep!

Steve.

Code: Select all

#include  "cr4_fft_1024_stm32.h"
#define   FFTLEN  1024
#define   LED PC13

uint16_t  reala;                       // value from from adc
uint16_t  realb;                       // value from from adc
uint16_t  imag = 0;
uint32_t  xa[FFTLEN];                  // acceleration wave form
uint32_t  ya[FFTLEN];                  // fft spectra
uint32_t  xb[FFTLEN];                  // acceleration wave form
uint32_t  yb[FFTLEN];                  // fft spectra
double    avg;
double    res = 3.3/4096.0;              // 12 bit resolution at 3.3V ref
double    sen = 0.3;                  // accelerometer sensitivity in volts/g
double    twopi = 6.283185307179;     // 2 X Pi used for fft 
double    gconv = 9806.65;            // gravity in mm/s/s
double    hz = 5;                     // 5 hz per bin





void adcsample()
{
  unsigned long start_time;
  unsigned long next_time;
  unsigned long end_time;
  int tot=0;

  
  if(micros()>0xFFF0BDBF)   // micros is less than 1 second until rollover
    delay(1010);            // 1.01 second delay to take micros past rollover

  avg=0;  
  start_time = micros();
  next_time = micros()+391;
  for(int a=0; a<FFTLEN; a++)
  {
    reala = analogRead(PA0);
    realb = analogRead(PA1);
    tot+=reala;
    xa[a] = (((uint16_t)(reala*16)) | ((uint32_t)(imag<<16)));
    xb[a] = (((uint16_t)(realb*16)) | ((uint32_t)(imag<<16)));
    for(;;)
      if((long)micros()>next_time)
        break;

  next_time+=391;
  }
  avg= (double) tot/FFTLEN;
  avg*=res;
}

void inplace_magnitude(uint32_t * target, uint16_t len)
{
  for (int i=0;i<len;i++){
     int16_t real = target[i] & 0xFFFF;
     int16_t imag = target[i] >> 16;
     uint32_t magnitude = sqrt(real*real + imag*imag);
     target[i] = magnitude; 
  }
}

void setup() {
    pinMode(PA0, INPUT_ANALOG);
    pinMode(PA1, INPUT_ANALOG);
    pinMode(LED, OUTPUT);
  	Serial.begin(115200); 
}

void loop() {
    int loopa;
    double acc=0;
    double vel=0;
    double accb=0;
    double velb=0;
    delay(5000);
    adcsample();
    digitalWrite(LED, HIGH);   // flash led to indicate adc read
    delay(100);              
    digitalWrite(LED, LOW);  
    
      
    cr4_fft_1024_stm32(ya, xa, FFTLEN); /*computes the FFT of the x[N] samples*/
    cr4_fft_1024_stm32(yb, xb, FFTLEN); /*computes the FFT of the x[N] samples*/
    
    inplace_magnitude(ya,FFTLEN); 
    inplace_magnitude(yb,FFTLEN); 
    
    ya[0]=0;
    Serial.print(acc,7);   
    Serial.print("\t");   
    Serial.println(vel,7);
    for(loopa=1; loopa<400; loopa++)
    {
      acc=(double)ya[loopa]*res*sen;
      vel=acc*gconv/(twopi*hz*loopa);
      accb=(double)yb[loopa]*res*sen;
      velb=accb*gconv/(twopi*hz*loopa);
      Serial.print(vel,7);
      Serial.print("\t");
      Serial.println(velb,7);   
    }
    for(;;);
} 


double hanning (int i, int nn)
{
  return ( 0.5 * (1.0 - cos (twopi*(double)i/(double)(nn-1))) );
}


User avatar
Pito
Posts: 1706
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: Trying to read button presses

Post by Pito » Mon Mar 27, 2017 11:51 am

What is the reason for multiplying the reala(b) by 16??
xa[a] = (((uint16_t)(reala*16)) | ((uint32_t)(imag<<16)));
Is it not this you want?

Code: Select all

xa[a] = (((uint32_t)(reala)) | ((uint32_t)(imag<<16)));
Pukao Hats Cleaning Services Ltd.

User avatar
efftek
Posts: 80
Joined: Tue Jan 10, 2017 9:42 pm
Location: Πάφος, Cyprus
Contact:

Re: Trying to read button presses

Post by efftek » Mon Mar 27, 2017 7:14 pm

[quote="Pito"]What is the reason for multiplying the reala(b) by 16??
quote]

The adc is 12 bits, maximum value 4096. The FFT uses 16 bit int, maximum value 65536 which divided by 4096 is 16 hence the real value is multiplied by 16 for 'proper scaling'.

It seems to be a point people are divided abaout Pito. I know you said you didn't think scaling mattered when doing an FFT and you definitely know a lot more about FFT's than me so I accepted it. Thank you for pointing out that I forgot to remove the *16

Steve.

Post Reply