Занимаясь некоторым извращением, а если быть точным, писал код в arduino ide под RP2040(планировался оптический приёмник в связке с с передатчиком Arduino nano на Atmega168p, но пока что увяз на самом процессе передачи). В чем суть возникшей проблемы:
Скетчи ниже
Использование delay() не принесло результатов, да и интересует меня в основном причина такого поведения, ибо хочется решить самому. Никакой мега-проблемы такой баг не создаёт, планирую использовать oled дисплей, но всё-же
- Система использует код Хэмминга(8,4) (никакой практической пользы в нём нет в данных условиях, просто спортивный интерес), и во время тестовых передач без его использования всё работает прекрасно
- Тут уже интереснее проблема, точнее первая вытекает отсюда, по абсолютно неизвестной мне причине декодирование кода Хэмминга происходит неверно(да и приём байт в целом), если в цикле заполнения буфера отсутствует вывод serial.
Скетчи ниже
Receibver:
#include <Arduino.h>
#define RECEIVEPIN 26
#define DIGRECEIVERPIN 11
#define THRESHHOLD 3320
#define BITRATE 400
#define BITPERIOD 1000/BITRATE
#define THFOBITPERIOD BITPERIOD*0.75
#define GET_BYTE(val, n) (((val) >> (8 * (n))) & 0xFF)
#define TEST
uint32_t _time;
uint32_t prevtime;
uint32_t fullTime = 0; // 32-битное полное время
uint16_t lastTime16 = 0; // последнее полученное 16-битное значение
bool firstPacket = true; // флаг первого пакета
uint32_t FullTime(uint16_t currentTime16) {
if (firstPacket) {
fullTime = currentTime16;
lastTime16 = currentTime16;
firstPacket = false;
return fullTime;
}
int16_t diff = currentTime16 - lastTime16;
if (diff < 0) {
diff += 65536;
}
fullTime += diff;
lastTime16 = currentTime16;
return fullTime;
}
void mig() {
for(int i = 0; i < 10; ++i) {
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
}
}
void setup()
{
pinMode(DIGRECEIVERPIN,INPUT);
_time = 0;prevtime = 0;
Serial.begin(115200);
mig();
Serial.print(F("Receiver start work"));
while(digitalRead(11)!=1){}
delayMicroseconds(THFOBITPERIOD*1000);
}
void loop()
{
preambleSearch();
uint8_t buffer[20];
for(int i = 0;i<10;++i)
{
uint8_t byte1 = receiveByte();uint8_t byte2 = receiveByte();
buffer[i*2] = byte1; buffer[i*2+1] = byte2;
//delay(200);
Serial.print(byte1,HEX); Serial.print(' '); Serial.print(byte2,HEX);Serial.print(' ');
}
Serial.println();
bool firstByte = decode(buffer[16],buffer[17]) == 0xAA;
bool secondByte = decode(buffer[18],buffer[19]) == 0x55;
if(firstByte && secondByte)
{
uint8_t bufferr[8];
for(int i = 0;i<8;++i)
bufferr[i]=decode(buffer[i*2],buffer[i*2+1]);
uint16_t data[4];
for(int i = 0;i<4;++i)
data[i] = (bufferr[i*2]<<8)|bufferr[i*2+1];
Serial.print(F("Transmitter time work: "));
Serial.print(FullTime(data[0])/1000);
Serial.print(F(" T = "));
Serial.print(data[1]*0.01);
Serial.print(F(" P = "));
Serial.print(data[2]+90000);
Serial.print(F(" H = "));
Serial.print(data[3]);
Serial.print('\n');}
}
bool preambleSearch()
{
uint16_t preamble = 0;
uint32_t bitbuffer = 0;
while(digitalRead(11)!=1){}
delayMicroseconds(THFOBITPERIOD*1000);
while (preamble != 0x4845)
{
bitbuffer = (bitbuffer<<1)|digitalRead(DIGRECEIVERPIN);
preamble = (decode(GET_BYTE(bitbuffer,3),GET_BYTE(bitbuffer,2))<<8)|decode(GET_BYTE(bitbuffer,1),GET_BYTE(bitbuffer,0));
delayMicroseconds(BITPERIOD*1000);
}
return true;
}
uint8_t receiveByte()
{
uint8_t byte = 0;
for(int i = 0;i < 8;++i)
{
byte = (byte << 1) | digitalRead(DIGRECEIVERPIN);
delayMicroseconds(BITPERIOD*1000);
}
return byte;
}
uint8_t decode(uint8_t byte1, uint8_t byte2)
{
return ((decodeHamming(byte1) << 4) | decodeHamming(byte2));
}
uint8_t decodeHamming(uint8_t sembyte) {
uint8_t d0 = (sembyte >> 7) & 1;
uint8_t d1 = (sembyte >> 6) & 1;
uint8_t d2 = (sembyte >> 5) & 1;
uint8_t d3 = (sembyte >> 4) & 1;
uint8_t p0 = (sembyte >> 3) & 1;
uint8_t p1 = (sembyte >> 2) & 1;
uint8_t p2 = (sembyte >> 1) & 1;
uint8_t parity = sembyte & 1;
uint8_t syn0 = d0 ^ d1 ^ d2 ^ p0;
uint8_t syn1 = d1 ^ d2 ^ d3 ^ p1;
uint8_t syn2 = d0 ^ d1 ^ d3 ^ p2;
uint8_t error_pos = (syn0 << 2) | (syn1 << 1) | syn2;
if (error_pos != 0) {
uint8_t bit_to_flip = 8 - error_pos;
switch (bit_to_flip) {
case 7: d0 ^= 1; break; // bit 7
case 6: d1 ^= 1; break; // bit 6
case 5: d2 ^= 1; break; // bit 5
case 4: d3 ^= 1; break; // bit 4
case 3: p0 ^= 1; break; // bit 3
case 2: p1 ^= 1; break; // bit 2
case 1: p2 ^= 1; break; // bit 1
case 0: parity ^= 1; break; // bit 0
}
}
uint8_t decSemByte = (d0 << 3) | (d1 << 2) | (d2 << 1) | d3;
return decSemByte;
}
Transmitter:
#include <GyverBME280.h>
#include <math.h>
#define LASER_PIN 9
#define MAXPACKETSIZE 25
#define BITRATE 400
#define BITPERIOD 1000/BITRATE
#define BITBLOCKSIZE BITRATE
#define BMEADRESS 0x76
#define PREAMBLE 0x4845
#define POSTAMBLE 0xAA55
#define CONSTANT 29.254
#define BAR 101325
#define TEST
GyverBME280 dataMaker;
uint16_t packet[6];
uint8_t HammingEncode(uint8_t sembyte);
void sendBlock(uint8_t *block);
const size_t SerialPrintf (const char *szFormat, ...)
{
va_list argptr;
va_start(argptr, szFormat);
char *szBuffer = 0;
const size_t nBufferLength = vsnprintf(szBuffer, 0, szFormat, argptr) + 1;
if (nBufferLength == 1) return 0;
szBuffer = (char *) malloc(nBufferLength);
if (! szBuffer) return - nBufferLength;
vsnprintf(szBuffer, nBufferLength, szFormat, argptr);
Serial.print(szBuffer);
free(szBuffer);
return nBufferLength - 1;
}
void setup()
{
Serial.begin(9600);
pinMode(LASER_PIN,OUTPUT);
packet[0] = PREAMBLE;
packet[5] = POSTAMBLE;
if (!dataMaker.begin(0x76)) Serial.println("Error!");
}
void loop()
{
setpacketPayload();
uint8_t buffer[(MAXPACKETSIZE-1)/2];
buffer[0] = 0x48;
buffer[1] = 0x45;
buffer[((MAXPACKETSIZE-1)/2)-2] = 0xAA;
buffer[((MAXPACKETSIZE-1)/2)-1] = 0x55;
for(int i = 1;i<6;++i)
{
buffer[i*2] = (packet[i]>>8) & 0xFF;
buffer[i*2+1] = packet[i] & 0xFF;
}
uint8_t encoded_packet[24];
for(int i = 0;i<12;++i)
{
encoded_packet[i*2] = HammingEncode((buffer[i]>>4)&0x0F);
encoded_packet[i*2+1] = HammingEncode(buffer[i]&0x0F);
}
sendBlock(encoded_packet);
delayMicroseconds(BITPERIOD*1000);
}
void setpacketPayload()
{
packet[1] = uint16_t(millis());
packet[2] = uint16_t(dataMaker.readTemperature() * 100);
packet[3] = uint16_t(dataMaker.readPressure()-90000);
packet[4] = uint16_t(CONSTANT*(dataMaker.readTemperature()+273)*log(BAR/dataMaker.readPressure()));
}
uint8_t HammingEncode(uint8_t sembyte)
{
uint8_t d0 = (sembyte >> 3) & 1;
uint8_t d1 = (sembyte >> 2) & 1;
uint8_t d2 = (sembyte >> 1) & 1;
uint8_t d3 = (sembyte >> 0) & 1;
uint8_t p0 = d0 ^ d1 ^ d2;
uint8_t p1 = d1 ^ d2 ^ d3;
uint8_t p2 = d0 ^ d1 ^ d3;
uint8_t parity = d0 ^ d1 ^ d2 ^ d3 ^ p0 ^ p1 ^ p2;
uint8_t byte = 0;
byte = (byte << 1) | (d0 & 1);
byte = (byte << 1) | (d1 & 1);
byte = (byte << 1) | (d2 & 1);
byte = (byte << 1) | (d3 & 1);
byte = (byte << 1) | (p0 & 1);
byte = (byte << 1) | (p1 & 1);
byte = (byte << 1) | (p2 & 1);
byte = (byte << 1) | (parity & 1);
return byte;
}
void sendBlock(uint8_t *block)
{
digitalWrite(LASER_PIN, 1);
for(int i = 0;i<24;++i)
{
sendByte(block[i]);
Serial.print(block[i],HEX);Serial.print(' ');
}
Serial.println();
}
void sendByte(uint8_t byte)
{
for(int i = 7;i>=0;--i)
{
digitalWrite(LASER_PIN, ((byte>>i)&1)); // Сдвиг вправо
delayMicroseconds(BITPERIOD*1000);
}
}