arduino - Page 1
Forum section: electronics / general

author: jafal
author_rank: Contributor
timestamp: December 12, 2020, 11:24:11 pm
content: hihow to control variables via serialint CYCLE_TIME_MIN = 1000;int CYCLE_TIME_MAX = 2000;int TX_PULSE_MIN = 50;int TX_PULSE_MAX = 150;int PULSE_1_MIN = 20;int PULSE_1_MAX = 70;int PULSE_1_DELAY_MIN = 10;int PULSE_1_DELAY_MAX = 30;int PULSE_2_MIN = 20;int PULSE_2_MAX = 70;int PULSE_2_DELAY_MIN = 50;int PULSE_2_DELAY_MAX = 250;those integers are variable how i can control them viaserial

author: sleemanj
author_rank: Super Contributor
timestamp: December 12, 2020, 11:50:50 pm
content: First they need to be volatileThen you need to implement reading a command from serial and updating the variable, in your main processling loop (void loop() { ... } in arduino-land).Code:void loop(){if(Serial.available()){// Do stuff with Serial.read() and probably atoi() here}}

author: jafal
author_rank: Contributor
timestamp: December 13, 2020, 12:40:54 am
content: Quote from: sleemanj on December 12, 2020, 11:50:50 pmthanks for you but i dontt know how to do itt

author: jafal
author_rank: Contributor
timestamp: December 13, 2020, 12:50:51 am
content: Quote from: sleemanj on December 12, 2020, 11:50:50 pmhican you explain how to change this just for(int i = 0; i < TX_PULSE; i++)and maybe i can learn for the restthanks in advance

author: ledtester
author_rank: Super Contributor
timestamp: December 13, 2020, 04:38:00 am
content: Tutorial on reading numbers from an Arduino serial port:https://youtu.be/q416XXJDE_MAs sleemanj mentioned, the counts need to be declared as volatile:volatile int TX_PULSE;Then use the above tutorial code to change TX_PULSE based on input from the serial port.

author: jafal
author_rank: Contributor
timestamp: December 13, 2020, 04:48:39 am
content: Quote from: ledtester on December 13, 2020, 04:38:00 amthey are volatilevolatile int CYCLE_TIME =1562;volatile int FREQUENCY = 640;volatile int TX_PULSE = 100;volatile int PULSE_1_DELAY = 20;volatile int PULSE_1 = 45;volatile int PULSE_2_DELAY = 150;volatile int PULSE_2 = 45;

author: jafal
author_rank: Contributor
timestamp: December 13, 2020, 04:57:57 am
content: Quote from: ledtester on December 13, 2020, 04:38:00 amthis is the code#include <TimerOne.h>volatile int CYCLE_TIME =1562;volatile int FREQUENCY = 640;volatile int TX_PULSE = 100;volatile int PULSE_1_DELAY = 20;volatile int PULSE_1 = 45;volatile int PULSE_2_DELAY = 150;volatile int PULSE_2 = 45;i want to control for(int i = 0; i < TX_PULSE; i++) the TX_PULSE and make it variable via serial read

author: ozcar
author_rank: Frequent Contributor
timestamp: December 13, 2020, 10:00:54 pm
content: Deleted - wrong thread!

author: sleemanj
author_rank: Super Contributor
timestamp: December 13, 2020, 10:20:59 pm
content: Quote from: jafal on December 13, 2020, 04:57:57 amAs I said, you need to implement that in your loop.https://www.arduino.cc/reference/en/language/functions/communication/serial/Something sort of likeCode:void loop(){if(Serial.available()){char cmd = Serial.read();switch(cmd){// Command "t", eg send "t 12345"case 't':{int input = Serial.parseInt(SKIP_ALL);if(int) { TX_PULSE = int; }}break;}}}

author: brucehoult
author_rank: Super Contributor
timestamp: December 14, 2020, 02:03:10 am
content: How many threads are you going to start with exactly the same thing?Try reading what people have already replied to you.

author: jafal
author_rank: Contributor
timestamp: December 15, 2020, 01:04:03 am
content: Quote from: sleemanj on December 13, 2020, 10:20:59 pmthanks alot i made it

author: jafal
author_rank: Contributor
timestamp: December 15, 2020, 01:16:55 am
content: Quote from: brucehoult on December 14, 2020, 02:03:10 amif i know how i wont bother others but i did itits my first time using arduino and i am very far away from programmingwhats upset you not all are R&DS same as you

author: Nominal Animal
author_rank: Super Contributor
timestamp: December 16, 2020, 02:53:34 am
content: How deep do you want to delve into this? You are a beginner programmer, and properly implementing this involves quite a few advanced data structures and methods.I would use arrays of variable descriptor structures, one array per variable type that can be modified. These structures reside in ROM/Flash, and identify the location in RAM where the volatile variable is. I also like to store the hardware default value in this structure. Here is an example sketch you can compile and run on e.g. Arduino Leonardo (including Pro Micro clones, treating them as Arduino Leonardos in the Arduino environment):Code:// SPDX-License-Identifier: CC0-1.0volatile int ivar;static const char ivar_label[] PROGMEM = "ivar";volatile int ifoo;static const char ifoo_label[] PROGMEM = "ifoo";volatile long lvar;static const char lvar_label[] PROGMEM = "lvar";volatile long lbar;static const char lbar_label[] PROGMEM = "lbar";volatile float fvar;static const PROGMEM char fvar_label[] = "fvar";// Helper function: Compares a string in RAM to a string in ROM/Flash, and returns true if they match.static bool label_match(const char *ramlabel, const char *PROGMEM romlabel) {while (1) {const char ramchar = (unsigned char)(*(ramlabel++));const char romchar = pgm_read_byte_near(romlabel++);if (romchar == '\0' && ramchar == '\0') {return true;} elseif (romchar != ramchar) {return false;}}}// Accessible volatile int variables with respective accessor functionsstatic const struct {volatile int *const reference;const char *const label PROGMEM;int const initial;} volatile_int[] PROGMEM = {{ &ivar, ivar_label, 1 },{ &ifoo, ifoo_label, 2 },};#define volatile_ints (sizeof volatile_int / sizeof volatile_int)static inline volatile int *volatile_int_reference(const size_t i) { return (volatile int *)pgm_read_ptr_near(&(volatile_int.reference)); }static inline const PROGMEM char *volatile_int_label(const size_t i) { return (const PROGMEM char *)pgm_read_ptr_near(&(volatile_int.label)); }static inline int volatile_int_initial(const size_t i) { return pgm_read_word_near(&(volatile_int.initial)); }static inline size_t volatile_int_find(const char *label) { for (size_t i = 0; i < volatile_ints; i++) if (label_match(label, volatile_int_label(i))) return i; return volatile_ints; }// Accessible volatile long variables with respective accessor functionsconst struct {volatile long *const reference;const char *const label PROGMEM;long const initial;} volatile_long[] PROGMEM = {{ &lvar, lvar_label, 3 },{ &lbar, lbar_label, 4 },};#define volatile_longs (sizeof volatile_long / sizeof volatile_long)static inline volatile long *volatile_long_reference(const size_t i) { return (volatile long *)pgm_read_ptr_near(&(volatile_long.reference)); }static inline const PROGMEM char *volatile_long_label(const size_t i) { return (const PROGMEM char *)pgm_read_ptr_near(&(volatile_long.label)); }static inline long volatile_long_initial(const size_t i) { return pgm_read_dword_near(&(volatile_long.initial)); }static inline size_t volatile_long_find(const char *label) { for (size_t i = 0; i < volatile_longs; i++) if (label_match(label, volatile_long_label(i))) return i; return volatile_longs; }// Accessible volatile float variables with respective accessor functionsconst struct {volatile float *const reference;const char *const label;float const initial;} PROGMEM volatile_float[] = {{ &fvar, fvar_label, 5.0f },};#define volatile_floats (sizeof volatile_float / sizeof volatile_float)static inline volatile float *volatile_float_reference(const size_t i) { return (volatile float *)pgm_read_ptr_near(&(volatile_float.reference)); }static inline const PROGMEM char *volatile_float_label(const size_t i) { return (const PROGMEM char *)pgm_read_ptr_near(&(volatile_float.label)); }static inline long volatile_float_initial(const size_t i) { return pgm_read_float_near(&(volatile_float.initial)); }static inline size_t volatile_float_find(const char *label) { for (size_t i = 0; i < volatile_floats; i++) if (label_match(label, volatile_float_label(i))) return i; return volatile_floats; }void setup() {// Initialize accessible volatile int variables to their initial valuesfor (size_t i = 0; i < volatile_ints; i++) *volatile_int_reference(i) = volatile_int_initial(i);// Initialize accessible volatile long variables to their initial valuesfor (size_t i = 0; i < volatile_longs; i++) *volatile_long_reference(i) = volatile_long_initial(i);// Initialize accessible volatile float variables to their initial valuesfor (size_t i = 0; i < volatile_floats; i++) *volatile_float_reference(i) = volatile_float_initial(i);Serial.begin(9600);}void loop() {while (!Serial) /* Nothing */;delay(10);Serial.print(F("ivar = "));Serial.print(ivar);Serial.print(F(", ifoo = "));Serial.print(ifoo);Serial.print(F(", lvar = "));Serial.print(lvar);Serial.print(F(", lbar = "));Serial.print(lbar);Serial.print(F(", fvar = "));Serial.println(fvar);// increment ivar.{size_t i = volatile_int_find("ivar");if (i < volatile_ints) {(*volatile_int_reference(i)) += 1;}}// negate fvar.{size_t i = volatile_float_find("fvar");if (i < volatile_floats) {volatile float *f = volatile_float_reference(i);(*f) = -(*f);}}// Delay for a second.delay(1000);}The sketch uses minimal RAM. Compile and run it, and look at Serial Monitor:ivarwill increment, andfvarbe negated at every iteration.The very first line withSPDX-License-Identifierstates that this file isLicensed under CC0-1.0. It means you can do anything you wish with this file, but without any warranties or guarantees from the author or copyright holder (me).The beginning of the sketch declares some volatile int, long, and float variables.Each accessible volatile int, long, or float variable has an associated_labelstored in ROM/Flash.Each accessible volatile type has an array in ROM/Flash (volatile_int[],volatile_long[], andvolatile_float[], above) of structures with three members: areferenceto the location of RAM for the volatile variable, alabelnaming the variable – the label does not need to match the variable name! –, and itsinitialvalue. You could omit the initial value stuff, but I included them since they are often very useful; and this way you can even "reset" a value to its initial value, simply by using thevolatile_type_initial(i)accessor function. They are used insetup()to set the variables to their desired initial values.(What are accessor functions? They are macro-like functions that access an array or data structure, hiding the complexities of such accesses. I could have implemented this as C++ classes, with proper accessor members, with a template to make it polymorphic (so it can be used with any scalar or structure data type you want).. but I didn't. One step at a time. As it is, the code above is compatible with C.)The functionvolatile_type_find(label)returns the index corresponding to the accessible volatile variable with the matching label, withlabelin RAM. If there is no such variable, the function returns the size of the array (defined as a macro,volatile_types).Ifiis a valid index, then(*volatile_type_reference(i)refers to the variable value; it is equivalent to using the volatile variable itself (except tiny bit slower, if we are precise). To initialize that variable to its initial value, you can do*volatile_type_reference(i) = volatile_type_initial(i);for example.Because the descriptor structures are in ROM/Flash, adding new variables' information to the arrays (so they can be accessed) does not require any RAM. (Only the variables themselves are in RAM.)The above example sketch does not include any serial input functionality. There are two basic approaches: One is to read serial input into a buffer, and when complete (for example, a newline is received), the buffer is parsed and acted upon. The other is a Finite State Machine that parses the input as it is received. The former is easier to implement, but typically uses more RAM than the latter; and the latter requires a well-formed input structure to be worth implementing as an FSM.Essentially, when your serial input parser has a label for a variable, it must usevolatile_type_find(label)to find which, if any, of the arrays know a variable with that label. (Note that this also tells you thetypeof the variable.) To set the value, or add, substract, multiply, or divide the value with some constant specified in the serial input, you then need to parse the serial input constant to the appropriate type, and finally update the value.Thus, the above sketch really includes everything except the serial input parsing part. Thelabel_match()helper function can also easily be modified to end the comparison at whitespace or non-alphanumeric character, in which case returning 0 in case of mismatch, and positive length in case of full label match, makes the buffer-based parser much simpler. (You can very easily support not just assignment '=', but also addition '+=', subtraction '-=', and scaling '*=' and '/=', for numeric types, too, if you use serial input format withlabel=value.)Even at ten dozen lines of code, including comments and empty lines, there is LOTS of stuff to understand there.

author: jafal
author_rank: Contributor
timestamp: December 16, 2020, 03:27:41 pm
content: Quote from: Nominal Animal on December 16, 2020, 02:53:34 amthaks for youmy aim was to control 3 outs in a variable timing in microsecond i made it by reading serial and return functionyour code is great