Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : maximite and GPIB/IEEE-488
Author | Message | ||||
robert.rozee Guru Joined: 31/12/2012 Location: New ZealandPosts: 2350 |
hi, first posting here, though i've been following the maximite for quite a while, with a view to using it as an instrument controller. has anyone looked at adding GPIB/IEEE-488 (HPIB) via the arduino connectors on the colour maximite, and writing the appropriate extensions to the basic? this would produce a neat little instrument controller that would be completely unique (as a modern product) and perhaps even highly desirable/marketable. the idea of using the arduino connectors would be to then have the GPIB connector mounted on the rear panel, leaving the 20 I/O pins on the expansion connector for controlling relays - another important part of any instrument controller. cheers, rob :-) |
||||
CircuitGizmos Guru Joined: 08/09/2011 Location: United StatesPosts: 1425 |
Is there an HPIB shield made by anyone? Micromites and Maximites! - Beginning Maximite |
||||
TinkersALot Regular Member Joined: 20/11/2012 Location: United StatesPosts: 72 |
I searched here: http://shieldlist.org/ for "HPIB" and came up with nothing, but I do not know if there is a better "all known shields" site that would offer better results. |
||||
robert.rozee Guru Joined: 31/12/2012 Location: New ZealandPosts: 2350 |
as far as i am aware, nobody makes one, but electrically the interface is quite simple. TTL signalling, an 8-bit bidirectional data bus, and another 8 control lines: EOI End-or-identify DAV Data valid NRFD Not ready for data NDAC Not data accepted IFC Interface clear SRQ Service request ATN Attention REN Remote enable people have made GPIB to serial converters using just the i/o pins on a (5 volt) pic directly. but the devil is in the details - without some 'intelligence' in a controller is can be quite complicated to manage the bus, hence the bigger part of the job being writing the basic extensions. just a GPIB to USB converter starts at several hundred dollars for a commercial product. |
||||
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 3802 |
Surely a GPIB-USB converter starts very cheaply such as this http://www.dalton.ax/gpib/ It would be easily changed from USB to another interface (RS232 or whatever) and could then connect to a 'mite. I have to say I don't see much interest for doing this so I reckon DIY :) John |
||||
boss Senior Member Joined: 19/08/2011 Location: CanadaPosts: 268 |
Hi, I'm considering to work with GPIB as well, and I found on the web this source code: http://bananawani-mc.blogspot.ca/2010/09/arduinogpib.html /* * GIPB Ether Adapter */ #include <string.h> #include <Ethernet.h> // Define PIN name #define DIO1 19 #define DIO2 18 #define DIO3 17 #define DIO4 16 #define DIO5 15 #define DIO6 14 #define DIO7 9 #define DIO8 8 #define EOI 6 #define DAV 5 #define NRFD 4 #define NDAC 3 #define IFC 7 #define ATN 2 #define REN GND #define SRQ GND // set MAC & IP byte mac[] = { 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ }; byte ip[] = { ZZZ, ZZZ, ZZZ, ZZZ }; byte gateway[] = { ZZZ, ZZZ, ZZZ, ZZZ }; byte subnet[] = { ZZZ, ZZZ, ZZZ, ZZZ }; Server server(ZZZ); // set Commando val char com[256] = ""; char c = 0; int p = 0; void setup() { // initialize the ethernet device Ethernet.begin(mac, ip, gateway, subnet); // start listening for clients server.begin(); // initialize gpib line pinMode(EOI, OUTPUT); digitalWrite(EOI, HIGH); pinMode(DAV, OUTPUT); digitalWrite(DAV, HIGH); pinMode(NDAC, OUTPUT); digitalWrite(NDAC, LOW); pinMode(NRFD, OUTPUT); digitalWrite(NRFD, LOW); } void loop() { int i; Client client = server.available(); if (client) { while (client.connected()) { if (0 < client.available()) { c = client.read(); *(com + p) = c; *(com + p + 1) = 0; p++; } if (';' == c) { *(com + p - 1) = 0; if (0 == strcmp("IFC", com)) { gpibIFC(); } else if (0 == strcmp("DCL", com)) { gpibDCL(); } else if (0 == strcmp("STA", com)) { gpibLineStatus(); } else { char command; int addr; char option[255]; sscanf(com, "%c%2d", &command, &addr); for (i = 4 ; i < strlen(com) ; i++) { option[i-4] = *(com + i); } option[i-4] = 0; strcat(option, "\r\n"); if ('W' == command) { gpibTalk((byte)addr, option); } else if ('R' == command) { char str[255] = ""; gpibListen((byte)addr, str, "\r\n"); server.println(str); } else if ('C' == command) { gpibSDC((byte)addr); } } *com = 0; p = 0; c = 0; } } } } void gpibLineStatus(void) { pinMode(ATN, INPUT); digitalWrite(ATN, HIGH); Serial.print(" ATN="); Serial.print(digitalRead(ATN)); pinMode(DAV, INPUT); digitalWrite(DAV, HIGH); Serial.print(", DAV="); Serial.print(digitalRead(DAV)); pinMode(NRFD, INPUT); digitalWrite(NRFD, HIGH); Serial.print(", NRFD="); Serial.print(digitalRead(NRFD)); pinMode(NDAC, INPUT); digitalWrite(NDAC, HIGH); Serial.print(", NDAC="); Serial.print(digitalRead(NDAC)); pinMode(EOI, INPUT); digitalWrite(EOI, HIGH); Serial.print(", EOI="); Serial.print(digitalRead(EOI)); Serial.print(", DIO8-1="); pinMode(DIO8, INPUT); digitalWrite(DIO8, HIGH); Serial.print(digitalRead(DIO8)); pinMode(DIO7, INPUT); digitalWrite(DIO7, HIGH); Serial.print(digitalRead(DIO7)); pinMode(DIO6, INPUT); digitalWrite(DIO6, HIGH); Serial.print(digitalRead(DIO6)); pinMode(DIO5, INPUT); digitalWrite(DIO5, HIGH); Serial.print(digitalRead(DIO5)); pinMode(DIO4, INPUT); digitalWrite(DIO4, HIGH); Serial.print(digitalRead(DIO4)); pinMode(DIO3, INPUT); digitalWrite(DIO3, HIGH); Serial.print(digitalRead(DIO3)); pinMode(DIO2, INPUT); digitalWrite(DIO2, HIGH); Serial.print(digitalRead(DIO2)); pinMode(DIO1, INPUT); digitalWrite(DIO1, HIGH); Serial.println(digitalRead(DIO1)); } byte get_dio() { byte x = 0; pinMode(DIO1, INPUT); bitWrite(x, 0, !digitalRead(DIO1)); pinMode(DIO2, INPUT); bitWrite(x, 1, !digitalRead(DIO2)); pinMode(DIO3, INPUT); bitWrite(x, 2, !digitalRead(DIO3)); pinMode(DIO4, INPUT); bitWrite(x, 3, !digitalRead(DIO4)); pinMode(DIO5, INPUT); bitWrite(x, 4, !digitalRead(DIO5)); pinMode(DIO6, INPUT); bitWrite(x, 5, !digitalRead(DIO6)); pinMode(DIO7, INPUT); bitWrite(x, 6, !digitalRead(DIO7)); pinMode(DIO8, INPUT); bitWrite(x, 7, !digitalRead(DIO8)); return x; } void set_dio(byte x) { pinMode(DIO1, OUTPUT); digitalWrite(DIO1, bitRead(~x, 0)); pinMode(DIO2, OUTPUT); digitalWrite(DIO2, bitRead(~x, 1)); pinMode(DIO3, OUTPUT); digitalWrite(DIO3, bitRead(~x, 2)); pinMode(DIO4, OUTPUT); digitalWrite(DIO4, bitRead(~x, 3)); pinMode(DIO5, OUTPUT); digitalWrite(DIO5, bitRead(~x, 4)); pinMode(DIO6, OUTPUT); digitalWrite(DIO6, bitRead(~x, 5)); pinMode(DIO7, OUTPUT); digitalWrite(DIO7, bitRead(~x, 6)); pinMode(DIO8, OUTPUT); digitalWrite(DIO8, bitRead(~x, 7)); } void gpibWrite(byte data) { // wait until (LOW == NDAC) pinMode(NDAC, INPUT); while (HIGH == digitalRead(NDAC)) { ; } // output data to DIO set_dio(data); // wait until (HIGH == NRFD) pinMode(NRFD, INPUT); while (LOW == digitalRead(NRFD)) { ; } // validate data pinMode(DAV, OUTPUT); digitalWrite(DAV, LOW); // wait until (HIGH == NDAC) while (LOW == digitalRead(NDAC)) { ; } digitalWrite(DAV, HIGH); set_dio(0); delayMicroseconds(10); return; } boolean gpibRead(byte *data) { boolean ret = false; // prepare to listen pinMode(NRFD, OUTPUT); digitalWrite(NRFD, HIGH); // wait until (LOW == DAV) pinMode(DAV, INPUT); while (HIGH == digitalRead(DAV)) { ; } // Ready for data digitalWrite(NRFD, LOW); // read from DIO *data = get_dio(); // check EOI pinMode(EOI, INPUT); if (LOW == digitalRead(EOI)) { ret = true; } else { ret = false; } // data accepted pinMode(NDAC, OUTPUT); digitalWrite(NDAC, HIGH); // wait until invalid data while (LOW == digitalRead(DAV)) { ; } digitalWrite(NDAC, LOW); return ret; // return true when EOI==LOW } void gpibTalk(byte addr, char *str) { // attention pinMode(EOI, OUTPUT); digitalWrite(EOI, HIGH); pinMode(ATN, OUTPUT); digitalWrite(ATN, LOW); delayMicroseconds(30); // unlisten gpibWrite(0x3F); delayMicroseconds(20); // talker address gpibWrite(0x40); delayMicroseconds(20); // listener address gpibWrite((byte)(0x20 + addr)); delayMicroseconds(20); // end of attention digitalWrite(ATN, HIGH); delayMicroseconds(20); // write string while (0 != *(str + 1)) { gpibWrite(*str); delayMicroseconds(20); str++; } // write last char digitalWrite(EOI, LOW); gpibWrite(*str); delayMicroseconds(20); digitalWrite(EOI, HIGH); } boolean gpibListen(byte addr, char *str, char* del) { // attention pinMode(ATN, OUTPUT); digitalWrite(ATN, LOW); delayMicroseconds(30); // unlisten gpibWrite(0x3F); delayMicroseconds(20); // talker address gpibWrite((byte)(0x40 + addr)); delayMicroseconds(20); // listener address gpibWrite(0x20); delayMicroseconds(20); // end of attention pinMode(NRFD, OUTPUT); digitalWrite(NRFD, LOW); pinMode(NDAC, OUTPUT); digitalWrite(NDAC, LOW); delayMicroseconds(10); digitalWrite(ATN, HIGH); delayMicroseconds(20); // recieve data int i, s, len = strlen(del); byte c; boolean isLast, isDel; s = 0; do { isLast = gpibRead(&c); *(str) = c; isDel = true; for (i = 0 ; i < len ; i++) { isDel = isDel & (*(str - i) == *(del + len - i - 1)); } str++; } while (!(isLast || isDel)); *(str) = 0; return true; } void gpibIFC(void) { pinMode(IFC, OUTPUT); digitalWrite(IFC,LOW); delayMicroseconds(128); digitalWrite(IFC, HIGH); } void gpibDCL(void) { // attention pinMode(ATN, OUTPUT); digitalWrite(ATN, LOW); delayMicroseconds(10); // send DCL gpibWrite(0x14); delayMicroseconds(10); // end of attention digitalWrite(ATN, HIGH); delayMicroseconds(20); } void gpibSDC(byte addr) { // attention pinMode(ATN, OUTPUT); digitalWrite(ATN, LOW); delayMicroseconds(10); // unlisten gpibWrite(0x3F); delayMicroseconds(10); // send ADDRESS for device clear gpibWrite((byte)(32 + addr)); delayMicroseconds(10); // send SDC gpibWrite(0x04); delayMicroseconds(10); // end of attention digitalWrite(ATN, HIGH); delayMicroseconds(20); } |
||||
CircuitGizmos Guru Joined: 08/09/2011 Location: United StatesPosts: 1425 |
So I would suppose if you change the Arduino code to be serial to GPIB, then you could mount an Arduino onto a ColorMax as if it were a shield. Extend the power and serial pins below the Arduino to mount the Arduino as if it were a shield. Snap a proto-shield on top of the Arduino that has the GPIB connector wired in place. MMBasic could control this through serial commands. Micromites and Maximites! - Beginning Maximite |
||||
boss Senior Member Joined: 19/08/2011 Location: CanadaPosts: 268 |
Greeting fro Vancouver, yes that's exactly what I'm thinking about. The next step should be to MM/CMM as the control unit. This design is good for testing purposes or work with just one "listener" because MM I/O cannot follow full GPIB electrical specification. Regards boss |
||||
CircuitGizmos Guru Joined: 08/09/2011 Location: United StatesPosts: 1425 |
Someone ambitious could always pull the "arduino code" into an appropriate AVR and design a GPIB shield. Micromites and Maximites! - Beginning Maximite |
||||
boss Senior Member Joined: 19/08/2011 Location: CanadaPosts: 268 |
Hi, absolutely, the there is just necessary to conditioned the cpu signals using the noniverting GPIB transceivers ie. DS75160/161/162 and that's it. I have couple of equipments I would like to control via GBIB bus. Regards boss |
||||
boss Senior Member Joined: 19/08/2011 Location: CanadaPosts: 268 |
Hi, another $5 GPIB solution including BASIC source code. You can download trial version BASCOM compiler(code limit 4kB which is more then enough) '*********************************************************** ******************* ' (c) Jan Petersen ' Orevej 6 ' DK 4760 Vordingborg ' jan_p@post8.tele.dk '----------------------------------------------------------- ------------------- ' Date: 24.02.2000 ' Compiler: Bascom AVR 1.0.8b ' File: Serial2Gpib.bas ' Description: RS232 to GPIB converter + ' HPGL to GDU converter ' ' This program is made specific for my Tektronix 4662 flatbed plotter ' with GPIB (IEE488) interface, and a strange GDU coordinate system..! ' Now it communicate whit a HPGL device-driver trough a normal ' RS 232 serialport. Hey man... '----------------------------------------------------------- ------------------- ' ' Input: ' RS232 :19200N81R ' Handshake :RTS/CTS specific for (Eagle CAM processor) ' ' Output: ' GPIB :DATA[0..7] (Inverted !Activ Low!) ' Handshake :DAV (DataValid) ' Handshake :NDAC (NoDataAccepted) ' Handshake :NRFD (NotReadyForData) '----------------------------------------------------------- ------------------- ' ' HPGL commands: Tektronix 4662 Plotter Commands: ' PU; (PenUp) M[cr] ' PD; (PenDown) D[cr] ' PA xxx,yyy; (PlotAbsolut) Dxxx,yyy[cr] ' VS xx; (VelocitySpeed) BYxx[cr] ' SP 0; (SelectPen) End Of File so goto home = M150,100[cr] ' ' GDU = GraphicDataUnit ' HPGL = HeweletPackardGraphicLanguage ' ' 1 GDU = 2.54 mm ' 1 HPGL unit = 0.025 mm ' ' 100 HPGL units = 1 GDU ' 1 HPGL units = 0.01 GDU ' ' All coordinates are divided by 100 ' ' A typical input format would look like this (Eagle Cam processor-HPGL driver) ' ' IN; IP 0,0,100,100; SC 0,100,0,100; ' VS 120 ' SP 2; ' PU; ' PA 19,18; ' PD; ' PA 1035,18; ' PU; SP 0; PA 0,0; ' ' Converted output to Tektronix plotter ' ' BY120 ' M0.19,0.18 ' D10.35,0.18 ' M150.100 '*********************************************************** ******************* $regfile = "2313def.dat" $crystal = 7372800 '7.372800 MHz crystal $baud = 19200 '@ 19.2 Kbaud error is 0.0% Dim Result As String * 15 Dim Value_x As String * 7 Dim Value_y As String * 7 Dim Low_ As String * 2 Dim High_ As String * 3 Dim Command As String * 1 Dim A As Byte , B As Byte Dim H As Byte , L As Byte , Data_inv As Byte ' Init ports --------------------------------------- Ddrd = &B00010100 Config Portb = Output Data_out Alias Portb 'Data byte to GPIB PortB 'RX PortD.0 'TX PortD.1 Rts_cts Alias Portd.2 'RTS/CTS handshake PortD.2 Dav Alias Portd.4 'DAV PortD.4 'NDAC PortD.5 'NRFD PortD.6 ' Start -------------------------------------------- set dav 'No DataValid on GPIB port Command = "M" 'set Command to MOVE Gosub _reset 'reset variable Reset Rts_cts 'uP ready ' Main loop ---------------------------------------- Do A = Waitkey() 'wait for a character set Rts_cts 'uP NOT ready Select Case A Case 10 : Gosub _reset 'linefeed Case 13 : Gosub _reset 'carriage return Case 32 : Gosub _space 'space Case 44 : Gosub _comma 'comma Case 59 : Gosub _semicolon 'semicolon Case Else : Result = Result + Chr(a) 'add the character to string End Select Reset Rts_cts 'uP ready Loop _space: ' SPACE '*************************************************** Select Case Result Case "VS" : Command = "V" 'VelocitySpeed Case "SP" : Command = "S" 'SelectPen Case "PU" : Command = "M" 'PenUp Case "PD" : Command = "D" 'PenDown End Select Gosub _reset Return _comma: ' COMMA '*************************************************** Value_x = Result 'value_x = X-coordinate Result = "" 'clear Result Return _semicolon: ' SEMICOLON '*************************************************** Select Case Command Case "V" : Gosub _vs 'Velocity Case "S" : Gosub _sp 'Select Pen Case "R" : Gosub _reset '/Dummy Chr...! End Select '/SP 0 command was detected '/in the _sp SUB '/means ..EOF.. Select Case Result Case "PU" : Command = "M" 'Move Case "PD" : Command = "D" 'Draw Case Else : Gosub _make_string 'value_y is in result End Select Gosub _reset Return _vs: ' PEN SPEED (velocity speed) '*************************************************** If Result <> "0" Then Result = "BY" + Result + Chr(13) Gosub _gpib_out 'BYxx[cr] End If Gosub _reset : Command = "M" Return _sp: ' SELECT PEN ' if a "SP 0" command is recived ' it means "MOVE HOME" and EOF '*************************************************** If Result = "0" Then Result = "M150," + "100" + Chr(13) Gosub _gpib_out 'M150,100[cr] Command = "R" '/R means EOF '/and is at dummy Chr '/used in _semicolon SUB Else Command = "M" End If Gosub _reset Return _make_string: ' Prepare the string to send to GPIB '*************************************************** If Result = "" Then Return If Value_x = "" Then Gosub _reset '/happens on the first line Return '/when value_x is NUL End If Gosub _divide 'value_Y is in result Value_y = Result 'value_Y = value_y / 100 Result = Value_x 'now value_X is in result Gosub _divide Value_x = Result 'value_X = value_x / 100 ' Assemble the string ----------------------------- Result = Command + Value_x + "," + Value_y + Chr(13) Gosub _gpib_out 'eg.Result = "M12.78,56[cr]" Gosub _reset Return _reset: ' Reset some variable ' This SUB saves lot of ROM Space.. :o) '*************************************************** Result = "" 'saves some program memory Value_x = "" 'when variables are cleared Value_y = "" 'in one SUB Return _divide: ' divide by 100 ' SINGLE aritmic don't work yet, so we do It like this..! '*************************************************** High_ = "" : Low_ = "" If Result = "0" Then Return 'don't divide, value is zero L = Len(result) 'length of string If L > 2 Then H = L - 2 If L = 1 Then Low_ = Right(result , 1) '1'st decimal value If L > 1 Then Low_ = Right(result , 2) '2'nd decimal value If L > 2 Then High_ = Mid(result , 1 , H) 'real value If L = 1 Then Result = "0.0" + Low_ '1 decimal If L = 2 Then Result = "0." + Low_ '2 decimal If L > 2 Then Result = High_ + "." + Low_ 'real + decimal B = Val(low_) If B = 0 Then Result = High_ 'ONLY real Return _gpib_out: ' Output data to GPIB port ' Data is inverted ' NRFS,NDAC and DAV is handshake '*************************************************** L = Len(result) 'how long is the string..? For H = 1 To L 'loop the string Low_ = "" 're use a old variable Low_ = Mid(result , H , 1) 'pick out the character Data_inv = 255 - Asc(low_) 'invert the character Bitwait Pind.6 , Set 'wait until (NRFD) goes HIGH Data_out = Data_inv 'Set the data on the port Reset Dav 'DataValid on port Bitwait Portd.6 , Reset 'wait until (NRFD) goes LOW Bitwait Pind.5 , Set 'wait until (NDAC) goes HIGH set dav 'Data NOT Valid on port Bitwait Portd.5 , Reset 'wait until (NDAC) goes LOW Next H Bitwait Pind.6 , Set 'wait until (NRFD) goes HIGH Return End |
||||
Print this page |