screen meter

I wonder if anyone could be bothered helping a puzzled newbie. It would be much appreciated.
Using an Arduino Uno, analogue reading a pot, sending it to a Pentium 4 for screen ouput in the form of a moving needle.
Very jerky needle movement and obviously dropping lots of data. I understood “myPort.bufferUntil(’/n’)” (see code) would throttle transmission. Is there any way of damping the needle movement to a smooth sweep? Tried everything — need suggestions (eat more fish ??).
Regards
/*
ARDUINO CODE

float sensVal;
float temp, diff;
int HYSTERESIS = 1;

void setup()
{
Serial.begin(9600);
}

void loop()
{
sensVal = analogRead(0);
for (int i=0;i<10;i++)
{
sensVal = sensVal + analogRead(0);
delay(10);
}
sensVal = sensVal/10;
diff = abs(sensVal - temp);
if (diff <= HYSTERESIS)
{
sensVal = temp;
}
temp = sensVal;
Serial.println(sensVal);
}
*/

//PROCESSING CODE

import processing.serial.*;
Serial myPort;
float angle=0.0000;

void setup ()
{
smooth();
size(1000,50);
myPort = new Serial(this, “COM18”, 9600);
myPort.bufferUntil(’\n’);
}

void draw()
{
}

void serialEvent(Serial myPort)
{
String val = myPort.readStringUntil(’\n’);
if(val != null)
{
val = trim(val);
angle = float(val);
background(255);
line(angle, height, angle, 0);
}
}

PLease modify your ppost, select the code and press the # button … (the quality is the same but the look is better :wink:

You 've read 11 times the analog sensor and divides by 10 …???

Tried everything — need suggestions (eat more fish ??).

If you tried really everything, there is no hope :wink:

I changed the floats into int as analog read returns ints, and divided it by the number of samples
(code patched, not tested or compiled)

#define NROFSAMPLES 20       // range 1..32

// EXPLICIT INITIALIZATION
int sensVal = 0;
int previous = 0;
int HYSTERESIS = 4;

void setup()
{
  Serial.begin(115200);          // speed up communication  - do this in processing to
  // Serial.println("Start");     // test communication 
}

void loop()
{
  sensVal = 0;
  for (int i=0; i<NROFSAMPLES; i++)
  { 
    sensVal += analogRead(0);
    delay(10);
  }
  sensVal = sensVal/NROFSAMPLES;

  if (abs(sensVal - previous) <= HYSTERESIS)
  {
    sensVal = previous ;
  } 
  else 
  {
    previous = sensVal;
  }
  Serial.println(sensVal);
  // delay(250);  // option slow it down 
}
  if (abs(sensVal - previous) <= HYSTERESIS)
  {
    sensVal = previous ;
  } 
  else 
  {
    previous = sensVal;
  }
  Serial.println(sensVal);

It would be even better to only send the value when it actually changed.

The process of converting the int to a string and sending the string (up to 4 characters plus the carriage return and line feed takes more time than would sending the high order byte and the low order byte, and reassembling the int in Processing.

If speed is an issue, send the two bytes and a separator, for a total of three bytes.

Many thanks for your suggestions. Your code is far more elegant than mine. If I do a for/next loop (in processing) with 0.1 or even 0.3 increments, I get the illusion of a smooth needle movement. So I thought I could create 'interpolations' between values with code to smooth movement but I couldn't get it to work (like I said, newbie !!). You are correct --- I am asking too much of the algorithms. Practically an infinite gradient of values from knob rotation. I must get missing values and 'jumps' !! I am now looking into subjects new to me, like 'serial buffers' and 'call and response' and 'handshaking??'. Your suggestion of high and low bytes would cut overhead. If I achieve any improvement I will post it under the same category/heading. Thanks again.....

I have looked further into "call & response" and "handshaking" and I don't think the answer to smooth needle movement lies in these areas. The physical input is close to an infinite gradient and must by nature be jerky. The answer lies in something called 'tweening". After all the needle jumps from position to position because of a gradient of values in between --- this merely uses code to interpolate these values on the screen.

I have looked further into "call & response" and "handshaking" and I don't think the answer to smooth needle movement lies in these areas.

Neither are designed to speed up the sending of data. They are designed to slow it down to manageable rates. Neither have anything to do with how that data is generated, sent, or consumed, so, your conclusions are quite reasonable.

The physical input is close to an infinite gradient and must by nature be jerky.

This statement needs some explanation. The input you are talking about is the output from the ADC chip on the Arduino, which is known to jitter, and is not infinite nor does it involve any gradients.

The answer lies in something called 'tweening".

I think the answer lies in Processing not drawing the needle in a new position unless doing so is warranted. What that means specifically, depends on what exactly is being measured by the Arduino, and how that measurement is being sent to/handled by Processing.

Care to post your current Arduino and Processing code?

Sorry --- I'm out of my depth. All this came about from trying to duplicate the smooth movement of an analogue meter needle digitally and on a monitor. Some visual 'stepping' can be expected --- 10 bit gives 1024 steps across a (say) 20 inch screen equals .020" steps, then there is screen resolution, e.g. pixel size, etc. etc. But I was getting more jerkiness than this which suggested dropped or 'skipped' data. Hence I was looking at serial data transmission technology for the answer. As I can get an experimental illusion of smooth needle movement with a for/next loop with 0.5 increment steps, I felt that an external 12 bit adc instead of the 10 bit on board adc might improve matters, and I have one coming. To 'copper my bets', I will also write some code to catch large gaps in the readings received by processing, and 'fill in' intervening steps. After all, there must be some there for the needle to have jumped to the other side of them!! Sorry to be so long-winded --- mental fuzz due to advanced age.

Have bought a couple of MCP 3201 ADC's. Interface is SPI. I'm out of my depth with C or bit level operations. Does anyone have simple Arduino (non-C) code to read a pot with this chip? I need to find out whether 12 bit instead of 10 bit will solve my problem. Hope someone out there is feeling benevolent. Regards

Further to my last post, I received a MCP3201 ADC. I am trying to interface it to the local version of an Arduino Uno (the Freetronics Eleven) with this code (simple test rig using a pot).
I just get a string of zeros.
Problem seems to be with the 3 lines “result =…”
I know zilch about bit banging — anyone got a clue what is wrong with this code ? I am completely stalled. Tried to find a clear exposition on the net of bit banging applied to interfacing an ADC with a uC via spi but no luck — or at least nothing a newbie could follow.
Regards…

#include <SPI.h>

const int slaveSelectPin = 10;
int result;
byte highByte;
byte lowByte;

void setup()
{
pinMode (slaveSelectPin, OUTPUT);
SPI.begin();
Serial.begin(9600);
}
void loop()
{
digitalWrite(slaveSelectPin, LOW);
delayMicroseconds(10);
highByte = SPI.transfer(0x00);
lowByte = SPI.transfer(0x00);
digitalWrite(slaveSelectPin, HIGH);
result = highByte << 8;
result = result | lowByte;
result = result >> 4;[/b]
Serial.println(result);
delay(100);
}

I know zilch about bit banging --- anyone got a clue what is wrong with this code?

That's fine, since there is no bit-banging going on here.

Further to my last post, I received a MCP3201 ADC. I am trying to interface it

Interface is a management word.

If you are in management, then you don't need to understand how the code works. Get a subordinate to connect the external ADC correctly, and write the code to communicate with it.

If you are not in management, you should not be using it. You should, instead, use real words to communicate what it is you are trying to do.

How is the ADC connected to the Arduino (clone)? What is connected to the ADC? In other words, how do you know that it has something valid to measure?

Problem seems to be with the 3 lines "result =..."

And the "problem" is?

Seems to me that there are a lot of places where the problem would be. If you are always seeing result equal 0, the code to manipulate highByte and lowByte is likely not the culprit.

Of course, you could verify whether it is the manipulation of highByte and lowByte that is the problem, or whether the valuation of highByte and lowByte is the problem, by simply printing highByte and lowByte.

Hi PaulS, thanks for your reply.
I’m not in anything, I just like learning new things. I’m 73 and have decided to live forever, and there is a lot to learn.
I have read explanations of galvanic skin response measurement that put variations in resistance down to stress causing perspiration. I did some tests that suggest to me that that is an over-simplification.
I wanted a device that would be more sensitive than the average GSR device — in the process I became dissatisfied with the smoothness of the needle movement I was achieving. I felt I should be able to achieve a movement closer to that of an analogue meter.
Body resistance readings with particular electrodes varies from about 250 Ohms to around 350,000 Ohms, and I was just using an ordinary pot to experiment with. I have now decided it was imperfections in pot material, wiper, etc. causing a lot of the problem. I tried your previous suggestion and learned to transmit and re-assemble bytes wiithout solving the problem.
I have since found some C# ‘bit banging’ code that I have managed to translate to Arduino code, and the extra 4X resolution from the new 12 bit 3201 has greatly smoothed things out. For interests sake, I substituted for the three “result =…” lines the following:—

result = ((0x1F & highByte) << 7) | (lowByte >> 1);

All is now ‘sweet’. I thank you for your interest and help. I was curious as to why the code I sent would not work, and I am still looking for a more succint exposition on bit banging.
Regards…

Just a thought, but you might want to raise the speed of your serial connection. In the example above the baud rate is set to 9600, which is good for humans reading text, but you can go much faster. Try raising the baud rate up up to 57,600 or 115,200 and see if that smooths things out.

FYI - Don’t forget to change the baud rate on the PC receiving the data.

willnue

The following couldn't work. I don't see why, of course, because I'm a newbie. But to save me chasing up a blind alley, someone might feel kind and tell me why. A 10 bit ADC will give 1024 steps in a 5 volt reference --- about 5 millivolt resolution. If I want 4096 steps giving 1.25 millivolt resolution, I need to shell out more for a 12 bit ADC. And so on. But what if a full differential ADC were used. Say a coarse (full Vref) reading were taken, and depending on the coarse value, the program drove a multiplexer to switch a voltage divider to give a sub-range reference e.g. if the coarse reading gave 3.62 volts, Vref would then be switched to a range from 3 volts to 4 volts. And so on. So the 1024 steps from a 10 bit ADC could be gotten to give a 1 millivolt resolution anywhere within the total 5 volt range. To take it further, you could theoretically get almost any desired resolution, up to the point where the resistor cost would outweigh any savings on ic. There's got to be a reason why it wouldn't work, probably because I don't fully understand what a differential input ADC does. Is that the case?

Say a coarse (full Vref) reading were taken, and depending on the coarse value, the program drove a multiplexer to switch a voltage divider to give a sub-range reference

A multiplexer can't do that.

Vref would then be switched to a range from 3 volts to 4 volts.

VRef defines the upper limit, not the range. The lower limit is always 0. In order for your scheme to work, you'd need to supply that VRef. How are you going to do that?

I thought the concept of 'earth' or 0 volts was a convenient mental 'tool', to explain that energy flows from a 'higher' energy source to a lower one. Therefore the lower voltage of the reference range set would be effectively '0'. Apparently not the case. Also I thought a multiplexer was a programmable switch that could switch in and out various elements of a voltage divider to give in effect a variable voltage reference -- I had not thought through the effect the earth of the resistor network would have, in that the higher reference voltage would be connected to earth thru the resistor network setting the lower reference voltage. I am wasting the forums time with elementary queries that I should handle by private study. Sorry. It's all rather facinating, and the Arduino will keep me busy learning for quite a while. Thanks to those who replied.

FYI- If you still want more resolution than your new MCP3201 12-bit ADC read this thread on the MCP3422 18-bit ADC. Shows example code etc...

Great 18-bit ADC for GPS and Proto Shield sensor logging http://forums.adafruit.com/viewtopic.php?f=31&t=12269

willnue