Friday, 7 March 2014

Arduino analogWrite with higher resolution

The other day I was troubleshooting a project that did not work as intended, so I eventually put down the problem as inadequate resolution. Even after averaging analogReads, reducing truncation errors and optimising everything it did not work much better.

Of course, ultimately the PWM analogWrite resolution is 8 bit on the Arduino UNO and my project did not even use it's full range, which limited it even more.

After some looking around I actually found out the atmega328 chip supports much higher PWM accuracy, up to 16 bit if necessary, but only on pins controlled by timer1. So I came up with a modified PWM routine that uses 10 bit resolution. (the 16 bit is a bit overkill once considering supply variations)


This is used by calling analogWrite10bit( pin , value); just like the original one but with 0 - 1023 range; Only timer1 pins can be used. That makes for pins 9 , 10 on the UNO and other atmega328 Arduinos. Once called even for one pin you can't use normal pwm on EITHER pins, so you have to use this routine for both.

Not tested on mega, leonardo but might work on corresponding timer1 pins.

//
//      GNU LESSER GENERAL PUBLIC LICENSE
//        Version 2.1, February 1999
//
//
// this was modified (slightly) from the arduino source code
//
// works on pins 9 , 10 on Arduino UNO
// once used *both* pins are set to 10 bit mode and "normal" analogWrite will not give correct results.
// uses timer one

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void analogWrite10bit(uint8_t pin, long val)
{
  // We need to make sure the PWM output is enabled for those pins
  // that support it, as we turn it off when digitally reading or
  // writing with them. Also, make sure the pin is in output mode
  // for consistenty with Wiring, which doesn't require a pinMode
  // call for the analog output pins.

  // set 10 bit mode

  sbi (TCCR1A , WGM11 );
 
  pinMode(pin, OUTPUT);
  if (val == 0)
  {
    digitalWrite(pin, LOW);
  }
  else if (val >= 1023)
  {
    digitalWrite(pin, HIGH);
  }
  else
  {
    switch(digitalPinToTimer(pin))
    {

#if defined(TCCR1A) && defined(COM1A1)
    case TIMER1A:
      // connect pwm to pin on timer 1, channel A
      sbi(TCCR1A, COM1A1);
      OCR1A = val;
      break;
#endif

#if defined(TCCR1A) && defined(COM1B1)
    case TIMER1B:
      // connect pwm to pin on timer 1, channel B
      sbi(TCCR1A, COM1B1);
      OCR1B = val;
      break;
#endif

//    case NOT_ON_TIMER:
//    break;
  
    default:
    analogWrite(pin , val / 4);
 
    }
  }
}



Wednesday, 6 November 2013

Coaxial SPDIF output for computer motherboard

So, I was walking around the shops with my girlfriend and I see a Battlefield 4 poster. I ask my g/f " This game is coming out sometime soon, right?"  "I don't really know" she probably says. I really don't remember these kind of answers. When I get home I search the net and find out it is released on 31 Oct (2013). It is 30'th. Something needs upgrading, My computer was state of the art years ago. So here come all sort of charts , cpu and gpu performances, and I decide to get a new cpu and motherboard, and hopefully get away without a new graphic card.

All that worked out quite well, except for the crappy socket 1150 cpu heatsink. Intel has changed the hole pattern by about 1mm, so all your old coolers that were designed for 125W cpus and would work fine on a 50W cpu are now rubbish. The stock cpu does get very hot. It got today to within 2 deg Celsius of it's limit, and it's only spring here in Australia. But that will get fixed as soon as I get my Noctua cooler mounting kit. It's free, too. Now that's good customer support.

This is about the sound issues. It seems in the time between my old motherboard and this one the industry has, for some strange reason, changed from the coaxial SPDIF output system to the apparently more fashionable optical system. I mean why use a coaxial cable with RCA plugs when you can use an optical cable that has no other use whatsoever, and it's even cumbersome to use. Times any rca cables have accidental become unplugged: zero .Times TOSLINK cables have become unplugged for no reason: at least one. And this is not only computers. When I was looking for a car stereo, the only one with an digital output was optical, too. Not so only a few years ago. Too bad they were way out of my price range.

Luckily there is an internal connector marked as digital output on the motherboard I have purchased. All I have to do now is drill some holes , make an adapter and hopefully we have sound. Yes, I could use the onboard sound, but it's really really terrible, especially if you plug headphones in it, like I had to do for the couple of days in which playing the game was a *much* higher priority.

The good news is it was easy to make such an adapter. It's only a couple of resistors, and the rca plug. All I had to do is measure the output to find out the voltage, and modify it to suit the coax SPDIF consumer standard which states 0.6V peak to peak signal.
So, after balancing the scope precariously on my computer chair, I had to measure the signal quickly. That is because my girlfriend was complaining about the noise the scope makes. In those days they had to put fans on things, or else they might not last 40 years. But, as usual, something was not working right. There was no signal. I , of course, start checking if there is a ground, if the scope is actually working (it was), etc. My girlfriend was not impressed. Eventually I figured out that, unlike my old realtek soundcard which played the output to both digital and analog simultaneously, this one only plays to one, or the other. Of course, this was one of the things I checked, but it turns out I had to reopen the player for the changes to work. Simple, really.

So, the signal is close to 3.3V, which means I needed a simple voltage divider and an rca plug. The ringing in the picture is from the scope. The divider works out to 75 and 330Ohms.
Note: Vin is on the motherboard side.  Vout is the rca plug middle pin. Refer to your motherboard manual to find out the pins.

The only other advice is to use in insulated rca socket in order to avoid a ground loop. Computers are really noisy and any ground loop will add jitter to the signal. Perhaps an optical sort of plug is required...

All in all this whole ordeal lasted only about , say, an hour. An adapter from ebay is surely, under $20.
I would like to believe an hour of my time is worth more than $20. The only thing I saved was the waiting time from ebay.

P.S. imho optical cables (really, the receiving socket) are very slow, and noisy, which is not good if low jitter is desired. My audio system is not earthed, and a coaxial cable does not introduce any ground loops. Jitter may or may not be an issue in audio, but I can measure it, and I can reduce it, too.
It is even possible that some jitter can be desirable, by masking and other mechanisms. The jury is out for now.


Tuesday, 29 October 2013

Subaru 22680 AA160 green airflow meter (AFM) dissasambly

Here are some pictures of my Subaru Liberty's (first series) AFM (air flow meter) which I removed from the car in order to troubleshoot what i perceive as a minor loss in performance at low rpms.

 After removing the rubber and breaking small bits of the case (nothing major) a nice copper screen is found.
 After the screen is gone the somewhat basic circuitry is not much to look at. It looks like the green transistor functions as a heater. The ceramic (?) main pcb has a couple of diodes which might be used to keep the temperature constant. The fifth pin, not connected internally is 5V on the harness. 
After desoldering the top board I found that this is about as much as this afm is going to be taken apart. The board is glued to the backing heatsink. Anyway, there is not much else to look at. The 2 screws hold the inner thermistor assambly. It could be removed  if needed.

I have not found out much during this exercise. The AFM uses unregulated 12V , but there is a regulator in the IC so that does not matter. The meter works, but presumably the printed film resistors or the thermistors are aging. I measured the thermistors as 530 Ohms for the small one and 20 for the larger, rectangular one. They are both PTC. (room temp 22C). With a hair drier they changed to 586 and 22.5.

My array of tests were mostly for fun. The AFM could be used to measure wind speed, but sadly I cannot think of a use for it right now (or ever). It's response time is good moving to higher amounts, and fairly bad from high to low (1 second). Output ranges from 0.2 approx at zero to 3V at my hairdryer's output (probably higher). The hairdryer was surprisingly repeatable with 1% error if placed in exactly same position.

Some error seems to be introduced by air temperature, but it was very small. No error is introduced by power supply voltage.

Since the grounds are connected together there might be ground loops present. I will look at the car wiring diagram in hope ground can be improved.

In conclusion if the afm calibration is off due to aging no used afm will be immune to it. Even new "old stock" units might have this problem. But without any reference there is no way to measure this item's calibration.