This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Sending PWM IR signals through nrf52832

Hello. 

I am wanting to send an infrared signal from my nrf52 DK (pca10040). I've found code online for sending custom IR signals using pwm and a gpio pin. The IR signals are 38kHz and I am wondering if that will work on the nrf52 DK.

#define txPinIR 11             //ASSIGN A DIFFERENT PIN HERE WHEN READY FOR TESTING

unsigned char carrierFreq = 38;
unsigned char period = (1000 + carrierFreq / 2) / carrierFreq;
unsigned char periodHigh = (period + 1) / 3;
unsigned char periodLow = period - periodHigh;



unsigned long sigTime = 0;     //used in mark & space functions to keep track of time
unsigned long sigStart = 0;    //used to calculate correct length of existing signal, to handle some repeats

#define NEC_HEX_VALUE 0xAAAAAAAAUL //UL makes this an unsigned long
#define NEC_BIT_COUNT 32

void sendHexNEC(unsigned long sigCode, byte numBits, unsigned char repeats, unsigned char kHz) {
  /*  A basic 32 bit NEC signal is made up of:
   *  1 x 9000 uSec Header Mark, followed by
   *  1 x 4500 uSec Header Space, followed by
   *  32 x bits uSec ( 1- bit 560 uSec Mark followed by 1690 uSec space; 0 - bit 560 uSec Mark follwed by 560 uSec Space)
   *  1 x 560 uSec Trailer Mark
   *  There can also be a generic repeat signal, which is usually not neccessary & can be replaced by sending multiple signals
   */
#define NEC_HEADER_MARK 9000
#define NEC_HEADER_SPACE 4500
#define NEC_ONE_MARK 560
#define NEC_ZERO_MARK 560
#define NEC_ONE_SPACE 1690
#define NEC_ZERO_SPACE 560
#define NEC_TRAILER_MARK 560

  unsigned long bitMask = (unsigned long) 1 << (numBits - 1); //allows for signal from 1 bit up to 32 bits
  //
  //if (carrierFreq != kHz)  initSoftPWM(kHz); //we only need to re-initialise if it has changed from last signal sent

  sigTime = micros(); //keeps rolling track of signal time to avoid impact of loop & code execution delays
  sigStart = sigTime; //remember for calculating first repeat gap (space), must end 108ms after signal starts
  // First send header Mark & Space
  mark(NEC_HEADER_MARK);
  space(NEC_HEADER_SPACE);

  while (bitMask) {
    if (bitMask & sigCode) { //its a One bit
      mark(NEC_ONE_MARK);
      space(NEC_ONE_SPACE);
    }
    else { // its a Zero bit
      mark(NEC_ZERO_MARK);
      space(NEC_ZERO_SPACE);
    }
    bitMask = (unsigned long) bitMask >> 1; // shift the mask bit along until it reaches zero & we exit the while loop
  }
  // Last send NEC Trailer MArk
  mark(NEC_TRAILER_MARK);

  //now send the requested number of NEC repeat signals. Repeats can be useful for certain functions like Vol+, Vol- etc
  /*  A repeat signal consists of
   *   A space which ends 108ms after the start of the last signal in this sequence
  *  1 x 9000 uSec Repeat Header Mark, followed by
  *  1 x 2250 uSec Repeat Header Space, followed by
  *  32 x bits uSec ( 1- bit 560 uSec Mark followed by 1690 uSec space; 0 - bit 560 uSec Mark follwed by 560 uSec Space)
  *  1 x 560 uSec repeat Trailer Mark
  */
  //First calcualte length of space for first repeat
  //by getting length of signal to date and subtracting from 108ms

  if (repeats == 0) return; //finished - no repeats
  else if (repeats > 0) { //first repeat must start 108ms after first signal
    space(108000 - (sigTime - sigStart)); //first repeat Header should start 108ms after first signal
    mark(NEC_HEADER_MARK);
    space(NEC_HEADER_SPACE / 2); //half the length for repeats
    mark(NEC_TRAILER_MARK);
  }

  while (--repeats > 0) { //now send any remaining repeats
    space(108000 - NEC_HEADER_MARK - NEC_HEADER_SPACE / 2 - NEC_TRAILER_MARK); //subsequent repeat Header must start 108ms after previous repeat signal
    mark(NEC_HEADER_MARK);
    space(NEC_HEADER_SPACE / 2); //half the length for repeats
    mark(NEC_TRAILER_MARK);
  }

}

void mark(unsigned int mLen)
{
  sigTime += mLen;
  unsigned long now = micros();
  unsigned long dur = sigTime - now;
  if (dur == 0) return;
  while ((micros() - now) < dur)
  {
    digitalWrite(txPinIR, HIGH);
    if (periodHigh) delayMicroseconds(periodHigh);
    digitalWrite(txPinIR, LOW);
    if (periodLow)  delayMicroseconds(periodLow);
  }
}

void space(unsigned long sLen)
{
  sigTime += sLen;
  unsigned long now = micros();
  unsigned long dur = sigTime - now;
  if (dur == 0) return;
  while ((micros() - now) < dur) ;
}

void setup() 
{
  Serial.begin(9600);
  //while(!Serial);
  delay(500);
  Serial.println(period);
  Serial.println(periodHigh);
  Serial.println(periodLow);
  
  pinMode(txPinIR, OUTPUT);

  periodHigh -= 3;
  periodLow  -= 7;
}

void loop()
{
  Serial.println(F("Sending NEC_HEX_VALUE @ 38kHz"));
  sendHexNEC(NEC_HEX_VALUE, NEC_BIT_COUNT, 0, 38);
  delay(5000); //wait 5 seconds between each signal (change to suit)
}

This is my code that is based on AnalysIR's forum on sending IR pwm. This code works well with my two arduino unos; I can send custom hex code signals and receive them on my other Arduino.

I use bsp from adafruit to upload the code from Arduino IDE to my dk but I've only gotten it to send a couple of signals that did not match the one I was intending to send. Most of the time it does not even send a signal out. 

Do I have to configure a pwm setting in the nrf52 dk or use a different pin? I assume sending 38kHz signals is not the problem so I would like to know if there is something I am missing that is specific to this board.

Thank you.

Parents Reply Children
No Data
Related