Hi,
I need to gen decimal point frequencies using a pin say 7.8 Hz easily using Arduino IDE.
Something like this would be great!
ledcAttachChannel(Out1, 7.8, 8, 1); //uint32_t freq is a float or 78 divided by 10 somehow?
Thanks
Please state what waveform, what frequency range and to what level of accuracy you wish to synthesize these alleged tones.
It can range from easy to lotsa fun!
It may help if you told us what's going on over there that is behind your inquiry.
Oh, and welcome to the forum.
a7
Try controlling the period rather than the frequency
7.8 Hz can be done reasonably with a simple millis() timer and bit banging....
Like said above: set the period... in milliseconds, so you will not need float...
on an ESP32 you won't get 7.8
but you can bit bang a pin
class SquareWaveGenerator {
private:
const uint8_t pin;
float freq;
unsigned long halfPeriod;
unsigned long lastMicros;
bool state;
void recalc() {
halfPeriod = 1000000ul / (freq * 2);
}
public:
SquareWaveGenerator(uint8_t p, float fHz = 10.0) : pin(p), freq(fHz), lastMicros(0), state(false) {
recalc();
}
void begin() {
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
}
void setFrequency(float fHz) {
if (fHz <= 0) return;
freq = fHz;
recalc();
}
void tick() {
unsigned long now = micros();
if (now - lastMicros >= halfPeriod) {
state = !state;
digitalWrite(pin, state ? HIGH : LOW);
lastMicros = now;
}
}
};
SquareWaveGenerator outputs[] = {
{3, 7.8},
{4, 15},
};
void setup() {
for (auto &o: outputs) o.begin();
}
void loop() {
for (auto &o: outputs) o.tick();
}
as long as you call tick() often enough, you should get your square wave (here in the example at 7.8Hz on pin 3 and 15Hz on pin 4.
const byte PinOut = 10;
const unsigned long UsecPeriod = 1000000L / (2 *7.8);
unsigned long usec0;
// -----------------------------------------------------------------------------
void loop ()
{
unsigned long usec = micros ();
if (usec - usec0 < UsecPeriod)
return;
usec0 = usec;
digitalWrite (PinOut, ! digitalRead (PinOut));
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (1000000);
pinMode (PinOut, OUTPUT);
Serial.println (UsecPeriod);
}
I’m sure you meant
digitalWrite (PinOut, digitalRead (PinOut) == HIGH ? LOW : HIGH);
![]()
no
(surely digitalRead() returns the correct type for the argument to digitalWrite())? but does negating it?
the implementers of digitalWrite() must have considered usage and defined
const bool HIGH = true;
const book LOW = false;
no they didn't. but they did make sure to define them as hex values
#define HIGH 0x1
#define LOW 0x0
Not in every core
To be strict, and I know everyone wants to, you have to play by the rules that the API exposes.
Use LOW and HIGH.
Use # defines
If you need to store a HIGH or LOW, use a variable
auto buttonState = LOW;
Maybe there's a legal way to toggle a button state less clumsy than
buttonState = buttonState == LOW ? HIGH : LOW;
The easiest is to leave HIGh and LOW very close to where they are required, and convert at that point to (or from) a variable that can hold true or false. Integer variables work, viz:
digitalWrite(somePin, someByte ? HIGH : LOW);
Or Boolean
bool isPressed = digitalRead(somePin) == LOW;
or
auto constPRESST = LOW;
//...
bool isPressed = digitalRead(somePin) == PRESST;
And let the compiler deal with the stupid long ago design decision to saddle this area with HIGH and LOW.
Toggle a pin? While relying on digitalRead to return the state of a pin
digitalWrite(somePin, digitalRead(somePin) == LOW ? HIGH : LOW);
yeah I use that in all my code. Not. But I should. Fortunately I'm not a slave to absolute correctness nor any style guide stuff.
a7
at work, a good reviewer would have said, correct the API
aren't these for the interrupts? should there be duplicated symbols for both.
a good reviewer would have said fix the API
apparently not those who defined the Arduino library
this project (mostly done by one of Banzi's students) was called Wiring ,
why is digitalRead() defined as
int digitalRead(uint8_t pin)
instead of have
DigitalState digitalRead (PinVal pin)
where DigitalState is the type defining the values passed to digitalWrite() and returned by digitalRead().
and i'd argue that it makes sense for DigitalValue to be a boolean since there are only 2 states and true to match the states defined in dataheets where true is typically high.
or should return values for something like fopen() be something other than NULL on failure. how often do you see
if (! fopen (filename, "r")) {
... error code
}
Yeah, too bad you weren't in the room.
a7
yet you say
sorta like people who should know better following people who don't
why not demonstate how it could be done with a different library
What? Or should I "huh?"?
I meant too bad no one had the sense to object to this HIGH LOW nonsense vigorously enough to prevail and kill it. Way back when.
What I do and don't as far as playing by anyone's rules is irrelevant.
I act like most people, sure that no one will ever pull the rug out from under us and break a crap-ton of source code.
I've even claimed to have a hat handy that I will eat if it happens. Not gonna happen.
Nevertheless, to be type correct it's what one has to do. Of all people, I would expect you to want to play by the strict rules.
a7
good questions...
see the discussion and links from Breakage caused by PinStatus and PinMode types · Issue #25 · arduino/ArduinoCore-API · GitHub
That works perfect. Thanks!
But the loop is stuck doing just that. It’s ok if your program does not need to do anything else.
You might want to reverse the if conditions and let the loop run if you need to handle something else.
Also you should use UL for unsigned long
UsecPeriod = 1000000UL / (2 *7.8);
The comment applies regardless of the platform, if you care enough to add a suffix to 1000000 then it’s probably a good idea to use the right type, and here I would say it’s unsigned as this is the number of microseconds in one second and we store the result into an unsigned long.
(But it does not matter much as it’s promoted to a floating point double to do the math, it’s just more for the sake of it)