Přepínání dvou podprogramů tlačítkem

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
jpokorny12
Příspěvky: 12
Registrován: 04 lis 2017, 20:05
Reputation: 0

Přepínání dvou podprogramů tlačítkem

Příspěvek od jpokorny12 » 06 říj 2018, 22:13

Zdravím
Chtěl bych se zeptat, jak přepínat dva podprogramy pomocí jednotlačítka. Tak nějak jsem poslepoval barevnou hudbu :) s FHT transformací a druhj podprogram je mod blikání. A přepíná se pomocí jednoho tlačítka. Z té barevky to přepne hned, jenže když je to v modu blikání musím držet tlačítko a až to dojede ten cyklus, tak to z něj vyskočí. Jde mi o to, jak to udělat, abych při zmáčknutí tlačítka hned vyskočil z toho blikacího podprogramu a skočil spídky do té barevky.
Díky

Kód: Vybrat vše

// HSV fade/bounce for Arduino - scruss.com - 2010/09/12
// Note that there's some legacy code left in here which seems to do nothing
// but should do no harm ...

// don't futz with these, illicit sums later
#define RED       9// pin for red LED
#define GREEN    10 // pin for green - never explicitly referenced
#define BLUE     11 // pin for blue - never explicitly referenced
#define SIZE    255
#define DELAY    20
#define HUE_MAX  6.0
#define HUE_DELTA 0.01

//long deltas[3] = { 5, 6, 7 };
long rgb[3];
long rgbval;
// for reasons unknown, if value !=0, the LED doesn't light. Hmm ...
// and saturation seems to be inverted
float hue=0.0, saturation=1, value=1;

/*
chosen LED SparkFun sku: COM-09264
 has Max Luminosity (RGB): (2800, 6500, 1200)mcd
 so we normalize them all to 1200 mcd -
 R  250/600  =  107/256
 G  250/950  =   67/256
 B  250/250  =  256/256
 */
long bright[3] = { 107, 67, 256};
//long bright[3] = { 256, 256, 256};

long k, temp_value;

void setup () {
  randomSeed(analogRead(4));
  for (k=0; k<3; k++) {
    pinMode(RED + k, OUTPUT);
    rgb[k]=0;
    analogWrite(RED + k, rgb[k] * bright[k]/256);
  }
}

void loop() {
  hue += HUE_DELTA;
  if (hue > HUE_MAX) {
    hue=0.0;
  }
  rgbval=HSV_to_RGB(hue, saturation, value);
  rgb[0] = (rgbval & 0x00FF0000) >> 16; // there must be better ways
  rgb[1] = (rgbval & 0x0000FF00) >> 8;
  rgb[2] = rgbval & 0x000000FF;
  for (k=0; k<3; k++) { // for all three colours
    analogWrite(RED + k, rgb[k] * bright[k]/256);
  }
  
  delay(DELAY);
}

long HSV_to_RGB( float h, float s, float v ) {
  /* modified from Alvy Ray Smith's site: http://www.alvyray.com/Papers/hsv2rgb.htm */
  // H is given on [0, 6]. S and V are given on [0, 1].
  // RGB is returned as a 24-bit long #rrggbb
  int i;
  float m, n, f;

  // not very elegant way of dealing with out of range: return black
  if ((s<0.0) || (s>1.0) || (v<1.0) || (v>1.0)) {
    return 0L;
  }

  if ((h < 0.0) || (h > 6.0)) {
    return long( v * 255 ) + long( v * 255 ) * 256 + long( v * 255 ) * 65536;
  }
  i = floor(h);
  f = h - i;
  if ( !(i&1) ) {
    f = 1 - f; // if i is even
  }
  m = v * (1 - s);
  n = v * (1 - s * f);
  switch (i) {
  case 6:
  case 0: 
    return long(v * 255 ) * 65536 + long( n * 255 ) * 256 + long( m * 255);
  case 1: 
    return long(n * 255 ) * 65536 + long( v * 255 ) * 256 + long( m * 255);
  case 2: 
    return long(m * 255 ) * 65536 + long( v * 255 ) * 256 + long( n * 255);
  case 3: 
    return long(m * 255 ) * 65536 + long( n * 255 ) * 256 + long( v * 255);
  case 4: 
    return long(n * 255 ) * 65536 + long( m * 255 ) * 256 + long( v * 255);
  case 5: 
    return long(v * 255 ) * 65536 + long( m * 255 ) * 256 + long( n * 255);
  }
} 

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od AstroMiK » 07 říj 2018, 09:26

Chyba bude právě v tom blikacím podprogramu, který tu neuvádíš.
Musíš tlačítko testovat rychleji a ne až na konci cyklu.
Nesmíš používat dlouhé pauzy, při kterých se program zastaví a k žádnému testování tlačítka nedochází.

Asi by se dal využít pin pro interrupt.

jpokorny12
Příspěvky: 12
Registrován: 04 lis 2017, 20:05
Reputation: 0

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od jpokorny12 » 07 říj 2018, 12:14

Tak kod ještě jednou :)
Takže se to chytne v tom cyklu a a už to ze všech vyjede tak se v jednu chvíli testuje tlačítko. A když to propásnu, tak musím čekat na další obrátku :)
Takže místo :) těch cyklů použít časovač a podle něj to srovnávat? Nebo jak funguje to přerušení? Jsem v tom docela nováček, ale snažím se :)


Kód: Vybrat vše

// Adjust the Treshold - what volume should make it light up?
#define THRESHOLD 30
// Attempt to 'zero out' noise when line in is 'quiet'.  You can change this to make some segments more sensitive.
int  oct_bias[] = { 170, 120, 54, 47, 100, 58, 100, 67  }; //2,5,7 used


// FHT defaults - don't change without reading the Open Music Labs documentation at openmusiclabs.com
#define LOG_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht
#define OCTAVE 1
#define OCT_NORM 0

#define DELAY 10

// LED pins
const int red = 11;    //BASS
const int blue = 10;  //MID
const int green = 9;     //HIGH

// Button mode stuff
const int button = 13;
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

#include <FHT.h> // include the library

/*===================================================================================
 * 
 *                                      SETUP
 * 
 ====================================================================================*/
void setup() {

  // Initialize Relay
  pinMode(red, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(green, OUTPUT);

  pinMode(button, INPUT);

  Serial.begin(9600); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0

}

/*===================================================================================
 * 
 *                              DRIVE LED FUNCTION
 * 
 ====================================================================================*/

void frequencyGraph(int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8) {


  if (x1 < 0) x1 = 0;
  if (x2 < 0) x2 = 0;
  if (x3 < 0) x3 = 0;
  if (x4 < 0) x4 = 0;
  if (x5 < 0) x5 = 0;
  if (x6 < 0) x6 = 0;
  if (x7 < 0) x7 = 0;
  if (x8 < 0) x8 = 0;

  // X2 Section of the Spectrum
  if (x2 > THRESHOLD && !digitalRead(red)) {
    digitalWrite(red, HIGH);
  }
  else if (x1 < THRESHOLD && digitalRead(red)) {
    digitalWrite(red, LOW);
  }

  // X5 Section of the Spectrum
  if (x5 > THRESHOLD && !digitalRead(blue)) {
    digitalWrite(blue, HIGH);
  }
  else if (x5 < THRESHOLD && digitalRead(blue) ) {
    digitalWrite(blue, LOW);
  }

  //X7 Section of the Spectrum
  if (x7 > THRESHOLD && !digitalRead(green)) {
    digitalWrite(green, HIGH);
  }
  else if (x7 < THRESHOLD && digitalRead(green)) {
    digitalWrite(green, LOW);
  }


}
/*===================================================================================
 * 
 *                             BUTTON UPDATE FUNCTION
 * 
 ====================================================================================*/
 bool buttonUpdate() {
     buttonState = digitalRead(button);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
      if(buttonPushCounter == 2) {
        buttonPushCounter = 0;
      }
    }
  }
  lastButtonState = buttonState;

  if(buttonPushCounter == 0)
  {
    return true;
  }
  else {
    return false;
  }
 }
 

/*===================================================================================
 * 
 *                                  MAIN LOOP
 * 
 ====================================================================================*/
void loop() {

  int q = 0;
  /*===================================================================================
 * 
 *                                MODE 0 LOOP
 * 
 ====================================================================================*/
  while (buttonUpdate()) {
    
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
      while (!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fht_input[i] = k; // put real data into bins
    }
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_octave(); // take the output of the fht
    sei();
    if (q % DELAY == 0) {
      for (int i = 0; i < 8; ++i) {
       Serial.print(fht_oct_out[i] - oct_bias[i]);
       Serial.print(" ");
      }
     Serial.println("");
      frequencyGraph(fht_oct_out[0] - oct_bias[0], fht_oct_out[1] - oct_bias[1], fht_oct_out[2] - oct_bias[2] - 10, fht_oct_out[3] - oct_bias[3], fht_oct_out[4] - oct_bias[4], fht_oct_out[5] - oct_bias[5], fht_oct_out[6] - oct_bias[6], fht_oct_out[7] - oct_bias[7]);
    }

    ++q;
  }
  //===============END MODE 0===============================

  /*===================================================================================
 * 
 *                                    MODE 1 LOOP
 * 
 ====================================================================================*/
  while (!buttonUpdate()) {

    int r, g, b;
    int FADESPEED = 1000;

    // fade from blue to violet
    for (r = 0; r < 256; r++) {
      analogWrite(red, r);
      delay(FADESPEED);
    }
    // fade from violet to red
    for (b = 255; b > 0; b--) {
      analogWrite(blue, b);
      delay(FADESPEED);
    }
    // fade from red to yellow
    for (g = 0; g < 256; g++) {
      analogWrite(green, g);
      delay(FADESPEED);
    }
    // fade from yellow to green
    for (r = 255; r > 0; r--) {
      analogWrite(red, r);
      delay(FADESPEED);
    }
    // fade from green to teal
    for (b = 0; b < 256; b++) {
      analogWrite(blue, b);
      delay(FADESPEED);
    }
    // fade from teal to blue
    for (g = 255; g > 0; g--) {
      analogWrite(green, g);
      delay(FADESPEED);
    }


  }
  //================END MODE 1==============================

}



Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od pavel1tu » 07 říj 2018, 16:47

Místo tlačítka dej přepínač a nemusíš nic složitě programovat ;-)
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

jpokorny12
Příspěvky: 12
Registrován: 04 lis 2017, 20:05
Reputation: 0

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od jpokorny12 » 08 říj 2018, 12:52

Ty jo :)
Obyčejnej :D přepínač a jednoduchá podmínka, že mě to nenapadlo :)
Díky

Ale i tak budu zkoušet :D proniknout do paralelního progrsmování. Máte k tomu nějakou doporučenou literaturu? Nebo od čeho se mám odrazit :)

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od pavel1tu » 08 říj 2018, 18:13

Paralelní běh programů, smyček a to několika - to je normální - třeba na Simaticu

1) Tohle je Arduino za 2USD
2) v jednoduchosti je síla

Jinak já nejdál došel na "já tomu říkám TASKY" - kusy programů, které se každý provádí jednou za pevně danou dobu, nebo se múže nějakou událostí vyvolat běh jiného tásky a zrušit opět jiný task
Používám tuto knihovnu <TaskScheduler.h> a je to zatím to NEJ co jsem na Arduino našel
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

petan
Příspěvky: 358
Registrován: 23 črc 2017, 10:19
Reputation: 0
Kontaktovat uživatele:

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od petan » 08 říj 2018, 19:35

pavel1tu píše:
08 říj 2018, 18:13
Paralelní běh programů, smyček a to několika - to je normální - třeba na Simaticu

1) Tohle je Arduino za 2USD
2) v jednoduchosti je síla

Jinak já nejdál došel na "já tomu říkám TASKY" - kusy programů, které se každý provádí jednou za pevně danou dobu, nebo se múže nějakou událostí vyvolat běh jiného tásky a zrušit opět jiný task
Používám tuto knihovnu <TaskScheduler.h> a je to zatím to NEJ co jsem na Arduino našel
Copak o to, "paralelní" běh částí programu není problém. Já používám jednoduché počítání interního časovače (viz článek https://www.mylms.cz/text-kusy-kodu-k-arduinu/#delay). Podobně to lze provést nějakým interním přerušením - to reálně přeruší kód a spustí se něco jiného. V podstatě lze i jednoduše vytvořit nějaké funkce a ty pouštět jednu za druhou. Knihoven na hlídání počítadla millis je plnej internet. Doporučuji např. kouknout na http://joysfera.blogspot.com/2015/03/ta ... duinu.html

Ale ve všech případech (kromě přerušení) nastane problém, pokud volaná funkce je časově náročná. I v Simaticu se spouští jednotlivé FB jeden za druhým. Simatic má ale v pozadí další logiku, která hlídá čas cyklu CPUčka. Pokud něco trvá dlouho (program se někde zacyklí) překročí čas cyklu nějakou nastavenou dobu a CPUčko spadne do chyby - svítí kontrolka ERR, nebo SF.

Stejně to je s Arduinem. Můžu něco pouštět v cyklu, nebo jednotlivé operace jednu za druhou. Ale pokud budu chtít, aby se něco provedlo každou sekundu a ve funkci budu mít 2s dlouhý delay, program prostě nebude fungovat tak jak má. Toto samozřejmě řeší přerušení, které je schopné kód utnout.

Samozřejmě, že neříkám, že delay je problém tohoto programu. Je tu nějaký časově náročný výpočet (nebo cykly), který by se musel buď předčasně ukončit nějakou další logikou, přerušením, nebo holt čekat až se výpočet ukončí. Dobré je program rozložit na jednotlivé krátké úseky. A podmínky kontrolovat mezi těmito úseky. Další možností je prostě použít výkonnější hardware. Je to podobné, jako hrát hru na starým počítači - vykreslení grafiky trvá delší dobu a pak se hra kouše. Prostě to počítač nestíhá...

Není tedy univerzální rada, ale člověk se musí zamyslet nad konkrétním problémem. Zde by se mohla např. v přerušení nahodit proměnná, že bylo tlačítko stisknuto a během smyčky, nebo po dokončení jedné smyčky kontrolovat, jestli bylo tlačítko stisklé. Nebylo by nutné ho držet do doby, dokud program neprojde správným místem. Samozřejmé je pak zpoždění reakce program - až program dojde do správného místa.

jpokorny12
Příspěvky: 12
Registrován: 04 lis 2017, 20:05
Reputation: 0

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od jpokorny12 » 09 říj 2018, 15:56

Díky za nápady, podívám se.
A mužeš mě prosím popsat jak funguje ta knihovna <TaskScheduler.h>? Aspoň nějak v základu
Díky

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od pavel1tu » 09 říj 2018, 17:07

jpokorny12 píše:
09 říj 2018, 15:56
Díky za nápady, podívám se.
A mužeš mě prosím popsat jak funguje ta knihovna <TaskScheduler.h>? Aspoň nějak v základu
Díky
Ve zkratce:
- umožňuje vykonávat části programu "jednou za daný čas"
- některé části se mohou spustit jen po spuštění arduina
- určené části se mohou spustit (jednou), nebo pravidelně spouštět za daný čas - při splnění nějaké podmínky
- u tasku může být čas jak často se má spouštět proměnný

asi toho umí více, viz dokumentace na github, je to jedna z nejlépe zpracovaných dokumentací co jsem viděl a to hlavní - projekt žije
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

jpokorny12
Příspěvky: 12
Registrován: 04 lis 2017, 20:05
Reputation: 0

Re: Přepínání dvou podprogramů tlačítkem

Příspěvek od jpokorny12 » 09 říj 2018, 21:42

Díky :)
Zkusím se tím nějak poprat. A zkusím se ještě mrknout na ty knihovny co využívají millis.
A když tak předělám ten blikací cyklus na millis aby se to nechytlo v těch cyklech :) a snad to bude nějak fungovat. A když tak přepínač to jistí
Díkec všem zůčastněným

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 24 hostů