Files
ggwave/examples/arduino-tx/arduino-tx.ino
Georgi Gerganov 3591285bd9 waver v1.5.2 : add option to shift the base tx/rx freqency
This can be used to easily change the frequency range of a protocols.
Make sure that the transmitter and receiver are using the same exact
shift.
2022-07-10 17:38:37 +03:00

177 lines
5.7 KiB
C++

// arduino-tx
//
// Sample sketch for transmitting data using "ggwave"
//
// Tested with:
// - Arduino Uno R3
// - Arduino Nano RP2040 Connect
// - NodeMCU-ESP32-S
//
// If you want to perform a quick test, you can use the free "Waver" application:
// - Web: https://waver.ggerganov.com
// - Android: https://play.google.com/store/apps/details?id=com.ggerganov.Waver
// - iOS: https://apps.apple.com/us/app/waver-data-over-sound/id1543607865
//
// Make sure to enable the "Fixed-length" option in "Waver"'s settings and set the number of
// bytes to be equal to "payloadLength" used in the sketch.
//
// Demo: https://youtu.be/qbzKo3zbQcI
//
// Sketch: https://github.com/ggerganov/ggwave/tree/master/examples/arduino-tx
//
#include <ggwave.h>
// Pin configuration
const int kPinLed0 = 13;
const int kPinSpeaker = 10;
const int kPinButton0 = 2;
const int kPinButton1 = 4;
const int samplesPerFrame = 128;
const int sampleRate = 6000;
// Global GGwave instance
GGWave ggwave;
char txt[64];
#define P(str) (strcpy_P(txt, PSTR(str)), txt)
// Helper function to output the generated GGWave waveform via a buzzer
void send_text(GGWave & ggwave, uint8_t pin, const char * text, GGWave::TxProtocolId protocolId) {
Serial.print(F("Sending text: "));
Serial.println(text);
ggwave.init(text, protocolId);
ggwave.encode();
const auto & protocol = GGWave::Protocols::tx()[protocolId];
const auto tones = ggwave.txTones();
const auto duration_ms = protocol.txDuration_ms(ggwave.samplesPerFrame(), ggwave.sampleRateOut());
for (auto & curTone : tones) {
const auto freq_hz = (protocol.freqStart + curTone)*ggwave.hzPerSample();
tone(pin, freq_hz);
delay(duration_ms);
}
noTone(pin);
digitalWrite(pin, LOW);
}
void setup() {
Serial.begin(57600);
while (!Serial);
pinMode(kPinLed0, OUTPUT);
pinMode(kPinSpeaker, OUTPUT);
pinMode(kPinButton0, INPUT);
pinMode(kPinButton1, INPUT);
// Initialize "ggwave"
{
Serial.println(F("Trying to initialize the ggwave instance"));
ggwave.setLogFile(nullptr);
auto p = GGWave::getDefaultParameters();
// Adjust the "ggwave" parameters to your needs.
// Make sure that the "payloadLength" parameter matches the one used on the transmitting side.
p.payloadLength = 16;
p.sampleRateInp = sampleRate;
p.sampleRateOut = sampleRate;
p.sampleRate = sampleRate;
p.samplesPerFrame = samplesPerFrame;
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
p.sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U8;
p.operatingMode = GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_TX_ONLY_TONES | GGWAVE_OPERATING_MODE_USE_DSS;
// Protocols to use for TX
GGWave::Protocols::tx().only(GGWAVE_PROTOCOL_MT_FASTEST);
// Sometimes, the speaker might not be able to produce frequencies in the Mono-tone range of 1-2 kHz.
// In such cases, you can shift the base frequency up by changing the "freqStart" parameter of the protocol.
// Make sure that in the receiver (for example, the "Waver" app) the base frequency is shifted by the same amount.
// Here we shift the frequency by +48 bins. Each bin is equal to 48000/1024 = 46.875 Hz.
// So the base frequency is shifted by +2250 Hz.
//GGWave::Protocols::tx()[GGWAVE_PROTOCOL_MT_FASTEST].freqStart += 48;
// Initialize the ggwave instance and print the memory usage
ggwave.prepare(p);
Serial.println(ggwave.heapSize());
Serial.println(F("Instance initialized successfully!"));
}
}
// Button state
int pressed = 0;
bool isDown = false;
void loop() {
delay(1000);
digitalWrite(kPinLed0, HIGH);
send_text(ggwave, kPinSpeaker, P("Hello!"), GGWAVE_PROTOCOL_MT_FASTEST);
digitalWrite(kPinLed0, LOW);
delay(2000);
digitalWrite(kPinLed0, HIGH);
send_text(ggwave, kPinSpeaker, P("This is a"), GGWAVE_PROTOCOL_MT_FASTEST);
send_text(ggwave, kPinSpeaker, P("ggwave demo"), GGWAVE_PROTOCOL_MT_FASTEST);
digitalWrite(kPinLed0, LOW);
delay(2000);
digitalWrite(kPinLed0, HIGH);
send_text(ggwave, kPinSpeaker, P("The arduino"), GGWAVE_PROTOCOL_MT_FASTEST);
delay(200);
send_text(ggwave, kPinSpeaker, P("transmits data"), GGWAVE_PROTOCOL_MT_FASTEST);
delay(200);
send_text(ggwave, kPinSpeaker, P("using sound"), GGWAVE_PROTOCOL_MT_FASTEST);
delay(200);
send_text(ggwave, kPinSpeaker, P("through a buzzer"), GGWAVE_PROTOCOL_MT_FASTEST);
digitalWrite(kPinLed0, LOW);
delay(1000);
digitalWrite(kPinLed0, HIGH);
send_text(ggwave, kPinSpeaker, P("The sound is"), GGWAVE_PROTOCOL_MT_FASTEST);
delay(200);
send_text(ggwave, kPinSpeaker, P("decoded in a"), GGWAVE_PROTOCOL_MT_FASTEST);
delay(200);
send_text(ggwave, kPinSpeaker, P("web page."), GGWAVE_PROTOCOL_MT_FASTEST);
digitalWrite(kPinLed0, LOW);
delay(1000);
digitalWrite(kPinLed0, HIGH);
send_text(ggwave, kPinSpeaker, P("Press the button!"), GGWAVE_PROTOCOL_MT_FASTEST);
digitalWrite(kPinLed0, LOW);
Serial.println(F("Starting main loop"));
while (true) {
int but0 = digitalRead(kPinButton0);
int but1 = digitalRead(kPinButton1);
if (but1 == LOW && isDown == false) {
delay(200);
++pressed;
isDown = true;
} else if (but1 == HIGH) {
isDown = false;
}
if (but0 == LOW) {
snprintf(txt, 16, "Pressed: %d", pressed);
digitalWrite(kPinLed0, HIGH);
send_text(ggwave, kPinSpeaker, txt, GGWAVE_PROTOCOL_MT_FASTEST);
digitalWrite(kPinLed0, LOW);
pressed = 0;
}
}
}