Array Usage Question

A sketch I've written works perfectly but it has 200 statements. I see a way to shorten it drastically (so it "looks" more like something one of you guys might have written instead of a novice like me) but I don't quite know how to write it. The following group is repeated 26 times successively in my sketch:

for (b1 = 0 ; b1 < n ; b1++) {
function() ; }
delayMicroseconds(600) ;
digitalWrite(A1,HIGH) ;

The value of "n" in the first line varies from group to group. I know how to create an array with the 26 values of "n" as follows:

[24,6,6,12,6,12,6,6,12,6,6,6,6,24,6,6,12,6,12,6,6,12,6,6,6,6]

Note that they are all integers except two are bytes. But I don't know how to pull them out of the array one by one as the sketch goes through the 26 repetitions.

A little help would be appreciated.

Try reading this:-
http://www.thebox.myzen.co.uk/Tutorial/Arrays.html

You can't do that, all the values in an array must be of the same type.

Is the array typed as Int? INT on Arduino 8-bit devices is actually int16_t But on 32-bit Arduinos, the INT is typed as int32_t.
A byte type is a byte, but it sounds like you are storing 2 bytes as int16_t and then splitting.

Personally, you have working code so I hesitate to take you into uncomfortable waters. May I suggest you consider "struct" and then create your array from that user-defined type (struct.)

https://forum.arduino.cc/t/defining-a-struct-array/43699

My rewording, "... all values in an array should be of the same type."

Pretty sure the compiler is doing automatic cast to int16_t and Op just has not encountered a failure with testing (yet. :no_mouth:)

I thought so. OK, just make it a byte array.

But what are you talking about? How have you defined the array?

The numbers are small enought to be fitted in a byte type, but it really doesn't matter for your pourposes.

byte -> 8 bit -> 2^8=256 (unsigned integer numbers from 0 to 255)

Anyway, If I have undestood well, for doing what you searching simply scan the array defined with a first for cycle and then use the i-value as "n" limit in the second for cycle.

int myArray[] = {24,6,6,12,6,12,6,6,12,6,6,6,6,24,6,6,12,6,12,6,6,12,6,6,6,6};

for(int i=0; i<sizeof(myArray)/sizeof(int); i++) {
  for(int j=0; i<myArray[i]; j++) {
    function() ; 
  }
  delayMicroseconds(600) ;
  digitalWrite(A1,HIGH) ;
}

But use

for(int i=0; i<sizeof(myArray)/sizeof(int); i++) {
  for(int j=0; i<myArray[i]; j++) {
    function(i, j) ;  

So your function knows what elements of the array you want to work in this time.

// The value of "n" varies
// array with the 26 values of "n" as follows:
const byte NValues[26] =
{
  24, 6, 6, 12, 6, 12, 6, 6, 12, 6, 6, 6, 6,
  24, 6, 6, 12, 6, 12, 6, 6, 12, 6, 6, 6, 6
};

void function() {}

void setup()
{

  for (byte i = 0; i < 26; i++)
  {
    // repeated 26 times
    byte n = NValues[i];

    for (byte b1 = 0 ; b1 < n ; b1++)
    {
      function();
    }
    delayMicroseconds(600);
    digitalWrite(A1, HIGH);
  }
}

void loop() {}

Be careful with what you write. Details matter.
INT is not a type.
The proper typename is int not INT

--- bill

johnwasser,

That last reply of yours looks encouraging. I haven't tried it yet. I know the forum always wants questions to include the Arduino code so everybody knows what you're talking about. I've been reluctant to do that because I wasn't sure if there were limits to how much code you wanted to see.

int b1 = 0;             // counter for carrier burst length
int b2 = 0;             // carrier cycles in burst = (4 x b2)
void setup()   {
pinMode(A1, OUTPUT);}   // output pin for IR LED signal
void loop() {
  for (b1 = 0; b1 < 24; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 12; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 12; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 12; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);

delay(30);

for (b1 = 0; b1 < 24; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 12; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 12; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 12; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
  for (b1 = 0; b1 < 6; b1++){
  carrier();}
  delayMicroseconds(600);
  digitalWrite(A1,HIGH);
digitalWrite(A1,LOW);

delay(2000);
}
void carrier() {        // this function generates 4 carrier cycles
  digitalWrite(A1,LOW);
  delayMicroseconds(12);
  digitalWrite(A1,HIGH);
  delayMicroseconds(12);
  digitalWrite(A1,LOW);
  delayMicroseconds(12);
  digitalWrite(A1,HIGH);
  delayMicroseconds(11);
  digitalWrite(A1,LOW);
  delayMicroseconds(11);
  digitalWrite(A1,HIGH);
  delayMicroseconds(11);
  digitalWrite(A1,LOW);
  delayMicroseconds(11);
  digitalWrite(A1,HIGH);
}

The above sketch puts out a near-perfect copy of the Sony MUTE infrared remote control signal on pin A1 of an Arduino NANO. If anyone doesn't believe that, just connect the anode of an IR LED to +5V and the cathode to A1 and point it at a Sony TV. The audio will go off and on repetively every 5 seconds.

Do you know that the delayMicroseconds only has a resolution of 4 microseconds, so using 12 and 11 is not going to give you the values you expect.

It is normal to use the PWM timers to get the modulation .

Since you always have the same two lines before the call to 'carrier()' and the same loop around the call to 'carrier()' the only part that changes is the number of times the four cycles of the carrier are repeated. You can shorten the code quite a bit by moving the two lines and the loop into the 'carrier()' function. The signal was repeated twice with a 30-millisecond gap between so, by moving the code into a separate 'signal()' function, it is possible to repeat the code without writing everything twice.

void setup()
{
  pinMode(A1, OUTPUT);  // output pin for IR LED signal
}  

void signal()
{
  carrier(24);
  carrier(6);
  carrier(6);
  carrier(12);
  carrier(6);
  carrier(12);
  carrier(6);
  carrier(6);
  carrier(12);
  carrier(6);
  carrier(6);
  carrier(6);
  carrier(6);
}

void loop()
{
  signal();
  delay(30);
  signal();

  delay(2000);
}

void carrier(int n)          // this function generates 4*n carrier cycles
{
  delayMicroseconds(600);

  for (int b1 = 0; b1 < n; b1++)
  {
    digitalWrite(A1, LOW);
    delayMicroseconds(12);
    digitalWrite(A1, HIGH);
    delayMicroseconds(12);
    digitalWrite(A1, LOW);
    delayMicroseconds(12);
    digitalWrite(A1, HIGH);
    delayMicroseconds(11);
    digitalWrite(A1, LOW);
    delayMicroseconds(11);
    digitalWrite(A1, HIGH);
    delayMicroseconds(11);
    digitalWrite(A1, LOW);
    delayMicroseconds(11);
    digitalWrite(A1, HIGH);
  }
}

There will be a little delay before I can resume this post. I worked on my sketch maybe three or four days with no problems using CH340 NANOs. During that period I opened and closed the IDE numerous times, plugged the NANO in and out numerous times, all the time with other stuff in adjacent USB sockets. But for the past day I haven't been able to get a NANO to hook up on the CH340 PORT. I've tried maybe a hundred times with a half dozen different NANOs, rebooting many times, restarting the IDE numerous times both before and after connecting the NANO, you can't think of a combination I haven't tried. There have been times when I saw a COM port listed in Device Manager with the CH340 label, but there was never a way to force the sketch to let me pick it. Oh, and I also downloaded Chinese CH340G drivers three times and uninstalled and installed them numerous times, always rebooting after, just in case. I love Arduino's but they are fragile as hell. Wish me luck.

The extremely cheap Chinese clones certainly can be, so buy a bunch of them and hope that you can get a couple to work reliably. For quality builds I pay a little more for boards from Sparkfun or Adafruit, which support and guarantee their products.

And by using an array, the whole program can be reduced to 42 lines. By using an array and count to describe the pulses, any Sony signals can be sent in one line.

void setup()
{
  pinMode(A1, OUTPUT);  // output pin for IR LED signal
}

// Number of carrier cycles for each pulse
const byte MuteCount = 13;
const byte MutePulses[MuteCount] = {96, 24, 24, 48, 24, 48, 24, 24, 48, 24, 24, 24, 24};

void signal(const byte pulses[], const byte count)
{
  for (int p = 0; p < count; p++)
  {
    delayMicroseconds(600);  // Delay between pulses
    carrier(pulses[p]);
  }
}

void SendTwice(const byte pulses[], const byte count)
{
  signal(pulses, count);
  delay(30);
  signal(pulses, count);
}

void loop()
{
  SendTwice(MutePulses, MuteCount);
  delay(2000);
}

// this function generates n carrier cycles
void carrier(int n)
{
  for (int b1 = 0; b1 < n; b1++)
  {
    digitalWrite(A1, LOW);
    delayMicroseconds(12);
    digitalWrite(A1, HIGH);
    delayMicroseconds(12);
  }
}

My results don't seem to support that statement. In my sketch the carrier frequency is established by the carrier function right before start of main loop. That function defines four carrier cycles with delayMicrosecond statements defining on and off times. Sony signals have a carrier frequency of 40 KHz, which is a cycle time of 25uS, which at 50% duty cycle is 12.5uS on and 12.5uS off, so I started by setting all the delayMicrosecond times to 12. I made a bunch of jpg pictures to include in this, but I can't find any "insert" button, so I'll just tell you what happened.

All 12's gave a carrier frequency of around 32 KHz. All 11's increased it to around 34 KHz. All 10's gave 37 KHz, all 9's pretty close to 40 KHz, all 8's 43 KHz. In ALL cases the demodulated wave form and the number of carrier cycles in each burst was near perfect Sony, and was always identified as Sony12 protocol and hex code 28 29 by my IRWidget (not surprising because IR receivers use the carrier frequency just as a horse for the raw signal to ride in on, and they do not check its frequency value as part of signal identification. The motivation to stick close to 40 KHz is the narrow bandpass filter in the optical receiver. As I recall, an off-center frequency deviation of 10% degrades the IR signal amplitude by about 50%, and thus reduces maximum transmission distance. Many years ago, for the fun of it, I souped up the carrier frequency of a Sony infrared signal to 100 KHz and it still worked close up.

I found that I could make fine tuning adjustments by not keeping all eight values in the function identical, but by mixing them up. Several times by fiddling with this I got perfect Sony replicas. But the oscillator in the Arduino NANO is not temperature stabilized, and seems to have a little jitter as well, so I expect variation is unavoidable. Fortunately it is far, far less than the allowable tolerance. Also, I did all my sketch development with a CH340 NANO, but the unit I finally got to work this morning is a CP2102 NANO, and who knows how closely those two guys' oscillators behave.

Time for rebuttal from Grumpy Mike. I'm anxious to get back to John's 42 line idea.

It doesn’t stop it being true though. Just look at the source code for the delay microseconds.

However it is your choice to ignore advice.
Bee seeing you.

Yes from the other periodic interrupts. Instability should not happen at these sorts of time scales.

Nothing to do with the USB / serial chip, it is the clock on the processor, it depends on if your processor is using a resonator or a crystal.

Grumpy,
I never ignore advice, even if it's a little caustic. I was aware the computer clock was not in the USB chip. I referred to the two NANOs by the type of USB chip only to identify them. I thought one might use a better type of oscillator than the other. Your comment gave me the idea -- why not just look and see. On the top side of the CH340 NANO there is a resonator connected to pins 7 and 8 of the MEGA328P computer chip, and on the bottom there is also a resonator connected to pins 7 and 8 of the CH340G USB chip. On the CP2102 NANO there is also a resonator connected to pins 7 and 8 of the MEGA328P chip .

Section 9 of the MEGA328P specifications has 11 pages of specs on the system clock and clock options. There's an internal 8 MHz RC clock oscillator so no external crystal or resonator is absolutely necessary. They refer to a calibrated 8MHz clock the user can calibrate to +/- 1% but which defaults on reset to +/- 10%. I don't understand any of this, but the resonator might explain why when I use millis() for a 3 minute time delay it is accurate within less than 0.6 of 1%.

I think I'm beginning to understand your comment about resolution. Looking over my data I can see that the changes I made in sketch timing did not result in the changes to carrier frequency I expected. Clearly something is going on here, and it may be the resolution problem. But high accuracy was never a goal of my sketch.

AMAZING ! I loaded John's 42 line sketch and it works perfectly, does everything my 218 line sketch did. I have one question:

lines 6, 7, and 8 are
// Number of carrier cycles for each pulse
const byte MuteCount = 12;
const byte MutePulses[MuteCount] = {96, 24, 24, 48, 24, 48, 24, 24, 48, 24, 24, 24, 24};

The carrier frequency is typically about 35 KHz. When I tried to make that 40 KHz by changing line 7 to byte MuteCount = 11 I get the following error:

too many initializers for 'const byte [12] {aka const unsigned char [12]}' What does that mean?

I mis-spoke. Your value was 13 and I got the error when I changed it to 12.