Re: Regarding rmt_tx library to transmit rawData to Mitsubishi AC
Posted: Tue Sep 29, 2020 8:26 am
by sam_wesleyIcapo
The code I am using is below for transmitter now:
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/ringbuf.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/rmt.h"
#include "driver/periph_ctrl.h"
#include "soc/rmt_reg.h"
#include <driver/adc.h>
#include <rom/ets_sys.h>
#define Duty_Cycle 56 //in percent (10->50), usually 33 or 50
//TIP for true 50% use a value of 56, because of rounding errors
//TIP for true 40% use a value of 48, because of rounding errors
//TIP for true 33% use a value of 40, because of rounding errors
#define Carrier_Frequency 40000 //usually one of 38000, 40000, 36000, 56000, 33000, 30000
#define PERIOD (1000000+Carrier_Frequency/2)/Carrier_Frequency
#define HIGHTIME PERIOD*Duty_Cycle/100
#define LOWTIME PERIOD - HIGHTIME
#define RMT_TICK_10_US (80000000/100/100000)
uint32_t period;
uint32_t periodOffset;
void nec_tx_init()
{
rmt_config_t rmt_tx;
rmt_tx.channel = 1;
rmt_tx.gpio_num = 18;
rmt_tx.mem_block_num = 7;
rmt_tx.clk_div = 100;
rmt_tx.tx_config.loop_en = false;
rmt_tx.tx_config.carrier_duty_percent = 50;
rmt_tx.tx_config.carrier_freq_hz = 32768;
rmt_tx.tx_config.carrier_level = 1;
rmt_tx.tx_config.carrier_en = true;
rmt_tx.tx_config.idle_level = 0;
rmt_tx.tx_config.idle_output_en = true;
rmt_tx.rmt_mode = 0;
rmt_config(&rmt_tx);
rmt_driver_install(rmt_tx.channel, 0, 0);
}
int rawData[]={3172, 1586, 394, 394, 394, 1182, 394, 394, 394, 394, 394, 1182, 394, 394, 394, 1182, 394, 394, 394, 394, 394, 1182, 394, 1182, 394, 1182, 394, 394, 394, 1182, 394, 394, 394, 1182, 394, 1182, 394, 1182, 394, 394, 394, 394, 394, 394, 394, 394, 394, 1182, 394, 1182, 394, 394, 394, 1182, 394, 1182, 394, 394, 394, 394, 394, 1182, 394, 394, 394, 394, 394, 1182, 394, 394, 394, 394, 394, 1182, 394, 1182, 394, 394, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 394, 394, 1182, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 1182, 394, 394, 394, 394, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 1182, 394, 394, 394, 1182, 394, 1182, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 1182, 394, 394, 394};
//int rawData[]={4384, 4322, 506, 1666, 506, 582, 506, 1668, 502, 1664, 506, 582, 504, 584, 506, 1664, 504, 586, 504, 582, 504, 1668, 502, 584, 504, 584, 508, 1662, 506, 1664, 506, 582, 506, 1666, 504, 582, 506, 582, 506, 582, 506, 1664, 506, 1664, 508, 1662, 506, 1664, 506, 1666, 506, 1662, 506, 1664, 506, 1666, 506, 582, 506, 584, 504, 582, 506, 586, 500, 584, 506, 580, 506, 584, 506, 582, 506, 582, 504, 1666, 504, 584, 506, 584, 504, 586, 506, 1662, 506, 1664, 506, 1664, 504, 1666, 504, 584, 508, 1662, 504, 1664, 506, 1664, 534, 5194, 4354, 4354, 510, 1662, 504, 582, 506, 1666, 504, 1664, 506, 584, 504, 584, 506, 1664, 506, 584, 506, 580, 506, 1664, 506, 584, 504, 584, 504, 1664, 504, 1664, 506, 584, 506, 1664, 504, 582, 504, 582, 506, 582, 506, 1664, 504, 1666, 504, 1664, 506, 1668, 502, 1666, 506, 1662, 504, 1666, 504, 1666, 504, 582, 508, 580, 506, 582, 504, 584, 506, 586, 502, 582, 504, 582, 506, 582, 506, 582, 504, 1664, 506, 582, 504, 584, 504, 586, 504, 1664, 504, 1664, 504, 1664, 506, 1664, 506, 582, 506, 1664, 506, 1664, 506, 1668, 504}; // COOLIX B21F08
//int rawData[]={3381,-1660,444,-1236,436,-1244,439,-428,413,-401,441,-399,442,-1238,435,-405,436,-431,411,-1243,440,-1240,442,-398,444,-1236,436,-431,411,-403,438,-1242,441,-1239,444,-423,408,-1245,438,-1243,440,-400,441,-399,443,-1237,435,-405,437,-430,411,-1243,440,-426,415,-399,443,-397,444,-396,435,-405,437,-404,437,-429,413,-401,440,-400,442,-398,443,-424,418,-395,436,-405,436,-404,438,-402,439,-401,440,-400,442,-398,443,-397,445,-395,436,-1245,438,-402,439,-427,415,-399,442,-398,443,-397,445,-1236,436,-1244,439,-401,441,-399,442,-398,443,-1238,435,-1245,438,-1242,441,-426,415,-425,417,-397,444,-396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21528,-8,27344,16379,1,0,0,4096,0,0,0,0,0,0,0,0,0,0,27376,16379,3052,16397,0,0,27,0,27520,16379,0,0,0,0,0,0,27408,16379,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27420,16379,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-9472,-9637,27877,16379,27876,16379,27408,16379,1104,22593,10612,16379,15264,16379,27520,16379,0,0,20,0,-30106,21106,15491,-13113,27520,16379,0,0,5,0,26748,16379,28772,29295,116,-12996,-16757,-2030,-22319,191,1,0,27512,16379,0,0,33,6,5,0,0,0,0,0,0,0,0,0,-26800,16378,-26904,16378,-27008,16378,0,0,0,0,1,0,0,0,11020,16192,0,0,7496,16384,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-21248,-10458,-32761,16381,-32760,16381,-32750,17586,20623,5485,18228,17283,-28985,6209,32766,20757,-19497,13714,10505,-15309,13323,-1751,5684,-2195,20760,-13644,-13039,10118,-9632,1374,2141,31530,-13234,17362,14740,24452,27814,-9606,6861,17286,-17868,-27523,-13463,-20790,-12961,13269,-31556,-10883,-16326,20923,21393,31394,-2046,31646,14755,-23511,31183,442,18068,-18165,28076,16379,27996,16379,27996,16379,27996,16379,27996,16379,0,0,28020,16379,-32767,-32767};
//#include "Arduino.h"
//#include <IRremote.h>
//DMA_ATTR int rawData[512];
// LED on Huzzah32 board
const int LED_BUILTIN = 13;
// structure used to initialize RMT inputs
// NOTE: tag is used on the monitor outputs to distinguish between channels
struct rmt_rx_inits {
rmt_channel_t channel;
gpio_num_t gpio_num;
uint8_t clk_div;
uint8_t mem_block_num;
bool config_filter_en;
uint8_t config_filter_tics_thresh;
uint16_t config_idle_threshold;
char tag[10];
}rx_inputs[1] = {
{ 1, 19, 80, 1, false, 0, 50000, "Ch1" }
};
// initialize RMT receive channels
void rx_channels_init() {
rmt_config_t rmt_rx;
size_t i;
size_t len = sizeof(rx_inputs) / sizeof( rx_inputs[0] );
for ( i=0; i<len; i++ ) {
rmt_rx.channel = rx_inputs.channel;
rmt_rx.gpio_num = rx_inputs.gpio_num;
rmt_rx.clk_div = rx_inputs.clk_div;
rmt_rx.mem_block_num = rx_inputs.mem_block_num;
rmt_rx.rmt_mode = RMT_MODE_RX;
rmt_rx.rx_config.filter_en = rx_inputs.config_filter_en;
rmt_rx.rx_config.filter_ticks_thresh = rx_inputs.config_filter_tics_thresh;
rmt_rx.rx_config.idle_threshold = rx_inputs.config_idle_threshold;
rmt_config(&rmt_rx);
rmt_driver_install(rx_inputs.channel, 1000, 0);
}
}
// initialize visible LED on ESP32 board
static void visible_led_init() {
gpio_pad_select_gpio(LED_BUILTIN);
gpio_set_direction(LED_BUILTIN, GPIO_MODE_OUTPUT);
}
/* Converts the RMT level, duration into a positive or negative integer
* Compatible with the ESP32-RMT-server application
* Note: most IR receivers have active-low outputs, where the
* ESP32-RMT-server application has active-high oututs
* This function inverts the RMT receive level so the text output is
* compatible with ESP32-RMT-server application
*/
int dur( uint32_t level, uint32_t duration ) {
if ( level == 0 ) { return duration; }
else { return -1.0 * duration; }
}
uint32_t max(uint32_t n1,uint32_t period)
{
if(n1>=period)
return n1;
else
return period;
}
uint32_t min(uint32_t n1,uint32_t period)
{
if(n1>=period)
return period;
else
return n1;
}
uint32_t calcUSecPeriod(uint32_t hz) {
if (hz == 0) hz = 1; // Avoid Zero hz. Divide by Zero is nasty.
uint32_t period =
(1000000UL + hz / 2) / hz; // The equiv of round(1000000/hz).
// Apply the offset and ensure we don't result in a <= 0 value.
return max((uint32_t)1, period);
}
void _delayMicroseconds(uint32_t time)
{
ets_delay_us(time);
}
//IRsend irsend(18);
void app_main() {
int channel = 1;
int data_size=sizeof(rawData)/sizeof(rawData[0]);
printf("%d\n",data_size);
//rx_channels_init();
//visible_led_init();
//nec_tx_init();
size_t size = (sizeof(rmt_item32_t) * (data_size/2));
gpio_pad_select_gpio(GPIO_NUM_18);
gpio_pad_select_gpio(GPIO_NUM_16);
gpio_set_direction(GPIO_NUM_18,GPIO_MODE_DEF_OUTPUT);
gpio_set_direction(GPIO_NUM_19,GPIO_MODE_DEF_INPUT);
gpio_set_level(GPIO_NUM_18,0);
//gpio_set_level(GPIO_NUM_19,0);
int read_raw;
adc2_config_channel_atten( ADC2_CHANNEL_7, ADC_ATTEN_0db );
esp_err_t r;
int64_t sigTime;
int64_t now;
int64_t dur;
int i,t;
i=0;
rmt_item32_t* item = (rmt_item32_t*) malloc(size);
int item_num = data_size/2;
memset((void*) item, 0, size);
int _dutycycle;
uint32_t freq=38;
uint32_t onTimePeriod,offTimePeriod;
/*int dec[13];
int dec1=0;
size_t num_channels = sizeof(rx_inputs) / sizeof( rx_inputs[0] );
size_t c, i,t;
size_t rx_size = 0;
int x=0;
rmt_item32_t* items = NULL;
// define ringbuffer handle
RingbufHandle_t rb;
// start receiving IR data
for ( c=0; c<num_channels; c++ ) {
rmt_rx_start(rx_inputs[c].channel, 1);
}*/
//each item represent a cycle of waveform.
while(1)
{
_dutycycle = 50;
if (freq < 1000) // Were we given kHz? Supports the old call usage.
freq *= 1000;
uint32_t period = calcUSecPeriod(freq);
uint32_t usec;
// Nr. of uSeconds the LED will be on per pulse.
onTimePeriod = (period * _dutycycle) / 100;
// Nr. of uSeconds the LED will be off per pulse.
offTimePeriod = period - onTimePeriod;
for (uint16_t i = 0; i < data_size; i=i+2) {
if (i & 1) { // Odd bit.
gpio_set_level(GPIO_NUM_18,0);
if ((int)abs(rawData)>0)
_delayMicroseconds((int)abs(rawData));
} else { // Even bit.
// Handle the simple case of no required frequency modulation.
usec=(int)abs(rawData[i+1]);
// Not simple, so do it assuming frequency modulation.
uint16_t counter = 0;
uint32_t elapsed ;
uint32_t usecTimer = esp_timer_get_time();
uint32_t start=usecTimer;
uint32_t now=esp_timer_get_time();
// Cache the time taken so far. This saves us calling time, and we can be
// assured that we can't have odd math problems. i.e. unsigned under/overflow.
if (start <= now) // Check if the system timer has wrapped.
elapsed = now - start; // No wrap.
else
elapsed = 4294967295 - start + now; // Has wrapped
//elapsed = usecTimer.elapsed();
while (elapsed < usec) { // Loop until we've met/exceeded our required time.
gpio_set_level(GPIO_NUM_18,1);
// Calculate how long we should pulse on for.
// e.g. Are we to close to the end of our requested mark time (usec)?
_delayMicroseconds(min((uint32_t)onTimePeriod, usec - elapsed));
gpio_set_level(GPIO_NUM_18,0);
counter++;
if (elapsed + onTimePeriod >= usec)
break; // LED is now off & we've passed our allotted time.
// Wait for the lesser of the rest of the duty cycle, or the time remaining.
_delayMicroseconds(
min(usec - elapsed - onTimePeriod, (uint32_t)offTimePeriod));
if (start <= now) // Check if the system timer has wrapped.
elapsed = now - start; // No wrap.
else
elapsed = 4294967295 - start + now; // Has wrapped // Update & recache the actual elapsed time.
}
}
}
gpio_set_level(GPIO_NUM_18,0); // We potentially have ended with a mark(), so turn of the LED.
// check each receive channel
//for ( c=0; c<num_channels; c++ ) {
// get the ring buffer handle
/* rmt_get_ringbuf_handle(rx_inputs[0].channel, &rb);
// get items, if there are any
items = (rmt_item32_t*) xRingbufferReceive(rb, &rx_size, 1000);
if(items) {
//dec[i++]=gpio_get_level(GPIO_NUM_16);
for(int x=0;x<199;x++)
{
dec1=0;
for(int j=0;j<13;j++)
{
r=adc2_get_raw( ADC2_CHANNEL_7, ADC_WIDTH_12Bit, &read_raw);
if ( r == ESP_OK ) {
if((read_raw)>700)
dec[j]=1;
else
dec[j]=0;
//printf("%d\n", read_raw );
}
}
for(int j=0;j<13;j++)
dec1+=(int)pow(2,12-j)*dec[j];
printf("%d,",dec1);
}
}*/
//printf("%d",dec[i-1]);
/*if(i==13);
{
for(int j=0;j<13;j++)
dec1+=(int)pow(2,12-j)*dec[j];
printf("%d ",dec1);
i=0;
dec1=0;
}*/
/*rmt_item32_t* item = (rmt_item32_t*) malloc(size);
int item_num = data_size/2;
memset((void*) item, 0, size);*/
/*dur=0;
now=0;
sigTime=esp_timer_get_time();
for(i=0;i<data_size;i=i+2)
{
sigTime+=(int64_t)abs(rawData[i]);
now=esp_timer_get_time();
dur=sigTime-now;
if(dur!=0)
{
while((esp_timer_get_time()-now)<dur)
{
gpio_set_level(GPIO_NUM_18,1);
vTaskDelay((HIGHTIME - 5)/(10000*portTICK_PERIOD_MS));
gpio_set_level(GPIO_NUM_18,0);
vTaskDelay((LOWTIME - 6)/(10000*portTICK_PERIOD_MS));
//printf("%s\n","check1");
}
}
sigTime+=(int64_t)abs(rawData[i+1]);
now=esp_timer_get_time();
dur=sigTime-now;
printf("duration=%lld\n",dur);
if(dur!=0)
{
while((esp_timer_get_time()-now)<dur)
{
//printf("%lld\n",esp_timer_get_time()-now);
//printf("%s\n","check0");
}
}
// printf("%s\n","check");
}*/
/*for(i=data_size-1,t=0;i>=0;i=i-2,t=t+1)
{
item[t].level0 = 1;
item[t].level1 = 0;
item[t].duration0 = (int)abs(rawData[i])/ (10 * RMT_TICK_10_US);
if((i-1)<0)
item[t].duration1 = (int)abs(0x7fff)/(10 * RMT_TICK_10_US);
else
item[t].duration1 = (int)abs(rawData[i-1])/(10 * RMT_TICK_10_US);
}
//To send data according to the waveform items.
rmt_write_items(channel, item, item_num, true);
//Wait until sending is done.
rmt_wait_tx_done(channel,1);*/
//before we free the data, make sure sending is already done.
//free(item);*/
//vTaskDelay(1/(38*10*portTICK_PERIOD_MS));
vTaskDelay(10/portTICK_PERIOD_MS);
}
}
The AC receiver is not giving a beep while I transmit data.But with remote,I am getting at the AC Receiver end.I have checked the AC receiver,the data received is able to be decode while I transmit but the beep is missing.Can I know what might be the cause for beep missing?