I am trying to control the spindle motor and the arm of a hard drive. I have been successful in controlling the motor but have problems with the later part.
I have attached the schematic I am using to make a shield for arduino. I am using a uno. So my basic idea is that I have a D/A converter MCP4725 (http://ww1.microchip.com/downloads/en/DeviceDoc/22039d.pdf). The output of D/A is connected to the non inverting input of an OPAMP in bipolar configuration (as mentioned in the datasheet of D/A). The opamp is powered by +,-5V both at 1.5A. The output of opamp is passed through a pair of matching transistor to amplify current in both polarities. The amplified signal is passed to the "arm" of the hard drive and before grounding is passed through a current sensor ACS712 (http://embedded-lab.com/uploads/datasheets/ACS712-Datasheet.pdf).
After burning components and replacing them finally I got the arm to move.
Now the problem is the arm does not move as I expect it to. I am giving a sine wave voltage which goes from -2.5 to 2.5 V outside of OPAMP. (0-5V from D/A --> opamp --> -2.5-to-2.5V). But the arm just moves rapidly up and down. I tried to measure the voltage at several points. The output of D/A shows random voltage when it is connected to opamp. If i disconnect it then I get the sine wave which I want. (i.e 0-5-0-5....)
Can someone help me figure out whats going on in there ?
I am giving a sine wave voltage which goes from -2.5 to 2.5 V outside of OPAMP. (0-5V from D/A --> opamp --> -2.5-to-2.5V).
I can't follow how you off-set 2.5 voltage. And resistor divider in negative feedback path shouldn't be at +5 V, but GND.
I'd suggest using one more OPA, having 2.5V as a reference ( gain 1) just to transform single polarity input to AC, and driving your PA (OPA + transistor ).
@MarkT
I have both 5V and -5V to the opamp. I am not really good at electrical circuits. So I am not sure what synthesize ground means and same with class AB and B. I have attached a better schematic.
Instead of GND, I have put it to 5V to make the signal bipolar. I did it according to the schematic given in the datasheet of MCP4725 D/A converter. I have put a link of the datasheet in my original post.
I have already tested the circuit(the bipolar output part) on a breadboard and it works fine. I also tested the entire circuit with matching transistors using a supply box at +,-5V,0.5A and everything worked fine. It is only after I made the pcb out of it these problems are creeping in. PCB was manufactured and assembled professionally. But why is this problem ?
Instead of GND, I have put it to 5V to make the signal bipolar. I did it according to the schematic given in the datasheet of MCP4725 D/A converter.
Oh, o'k. Now I understand. Other things, which confuse me:
I am giving a sine wave voltage which goes from -2.5 to 2.5 V outside of OPAMP. (0-5V from D/A --> opamp --> -2.5-to-2.5V).
Your PA has a gain 10. So output of DAC has to be 0.5 V peak-to-peak, 0 to 0.5 V centered around 0.25 V. How you generate a sine wave? DC off-set in your configuration comming from the microcontroller, what I think, you should look in the code, if there is correct scale / bias of the sine, no overdrive and etc.
DC off-set in your configuration comming from the microcontroller, what I think, you should look in the code, if there is correct scale / bias of the sine, no overdrive and etc.
I am attaching the sketch also. I am not exactly giving a sine wave but increasing the bytes from 0 to 4095 and back to 0 in steps of 250 ( an approximated sine). Do you think this is the problem ??
--ksp
byte Program = 64;
byte Device = 96; // This hardwired into the IC
int maxValue = 4095;
int minValue = 0;
int value = 4095;
int dir = 250;
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
byte b1 = byte((value / 16));
byte b2 = byte(value % 16);
Wire.beginTransmission(Device);
Wire.write(Program);
Wire.write(b1);//(value >> 4);
Wire.write(b2);//((value & 15) << 4); // Needed twice, since the 4 lowest bits (of 12) are in the fourth byte
Wire.endTransmission();
value = value + dir;
if(value > maxValue) dir = -250;
if(value <= minValue) dir = 250;
delay(3000);
}
Your opamp feedback network is referenced to +5V for some reason - I think you seem to be expecting a 741 to work from 0V to +5V when supplied with +5V and -5V - it probably won't. You need to use a low voltage opamp, not a 741 (its only characterised for +/-15V supplies in the datasheet).
Can you redraw the circuit the right way up please, it'll be much easier to understand (+ve rail at the top, -ve rail at the bottom, signals travel left to right).
In particular your output stage doesn't make any sense to me - why is the output only used for feedback? Have you missed the load from the diagram?
12-bit DAC , triangle wave at the output should be 0 - 409.5, to produce 0 - 0.5 V . "0" would be 204.8
You can't "scale" your triangle wave by division 16 (or shifting 4 to right), because it's changing all references. Try division by 10.
Other way to generate a sine, is generate AC bipolar form in the code ( from -204 to + 204 ), and add 204 off-set later on, it's easier to "scale" magnitude AC.
@MarkT
Sorry for the diagram, I am not familiar with drawing schematics, this is the second time I am doing it. I will try to make it more legible.
The output feedback is referenced to +5V to make the 741 work between -2.5 to 2.5V i.e, to shift the D/A output of 0-5V. Please check the datasheet of D/A converter, I used the bipolar application circuit.
Yes I have left the load out of the diagram. It is connected to the terminal which is labeled "coil".
@Magician
I will try the division by 10 and get back with the results.
Thinking little bit more about what they say in data sheet, I find out that basically I was right about "scaling" and offset, but my math isn't correct. Don't know why you decide to make a gain 10, but its highly complicate calculation of the offset voltage. VDD depends on gain, so you can't just connect +5V power line as VDD and pick up any gain you want ( with resistors 910 and 100).
i have run the following code on just the D/A converter and the output of it is ~3V no matter which conversion I use.
byte Program = 64;
byte Device = 96; // This hardwired into the IC and the BoB, in other words, it is a given.
int maxValue = 4095;
int minValue = 0;
int value = 4092;
int dir = 250;
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
// byte b1 = value >> 4;
// byte b2 = (value & 15)<< 4;
// byte b1 = byte(value/16);
// byte b2 = byte((value % 16) << 4);
byte b1 = byte(value/10);
byte b2 = byte(value % 10);
Wire.beginTransmission(Device);
Wire.write(Program);
Wire.write(b1);
Wire.write(b2); // Needed twice, since the 4 lowest bits (of 12) are in the fourth byte
Wire.endTransmission();
Serial.print(value);Serial.print("\t");Serial.print(b1);Serial.print("\t");
Serial.print(b2);Serial.print("\n");
// value = value + dir;
if(value > maxValue) dir = -250;
if(value <= minValue) dir = 250;
delay(3000);
}
Can I just re-state that the 741 is not guaranteed to work at all with the inputs/outputs within 3V of a supply rail (make that 4V if the outputs are loaded by lower than 10k impedance). Its a very poor choice of opamp with rail-to-rail 5V-compatible ones abound these days.
@MarkT
This program worked and the problem was the device address. Once I have put in the address it the D/A converter was working good. But as you have said I think the OPAMP is causing problems. I should change it in the next iteration.
Can you suggest a replacement for the 741 opamp.
I will post the output I am currently receiving in the next post.
byte Program = 64;
byte Device = 100;
int maxValue = 4075;
int minValue = 0;
int value = 4075;
int dir = -250;
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
byte b1 = value >> 4;
byte b2 = (value & 15)<< 4;
Wire.beginTransmission(Device);
Wire.write(Program);
Wire.write(b1);
Wire.write(b2); // Needed twice, since the 4 lowest bits (of 12) are in the fourth byte
Wire.endTransmission();
Serial.print(value);Serial.print("\t");Serial.print(b1);Serial.print("\t");
Serial.print(b2);Serial.print("\n");
value = value + dir;
if(value >= maxValue) dir = -250;
if(value <= minValue) dir = 250;
delay(1000);
}