/* TDK Lambda ZUP control Copyright I.Tsurin Liverpool University V1.0 (30.11.2021) */ /* https://www.emea.lambda.tdk.com/de/KB/ZUP-User-Manual.pdf */ /* http://slackware.osuosl.org/slackware-3.3/docs/mini/Serial-Port-Programming */ /* type command /var/log/lsusb to find ttyUSBxx info */ #include /* Standard input/output definitions */ #include /* Standard libraries definitions */ #include /* String function definitions */ #include /* UNIX standard function definitions */ #include /* File control definitions */ #include /* Error number definitions */ #include /* POSIX terminal control definitions */ #include #define Wsize 65 /* The longest string has 64 characters */ int fd; int InitPort(void) { struct termios options; fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { fputs("Unable to open port\n", stdout); return 0; } else { tcgetattr(fd, &options); cfsetispeed(&options, B9600); /* Set the input baud rate */ cfsetospeed(&options, B9600); /* Set the output baud rate */ options.c_cflag |= (CLOCAL | CREAD); /* Enable receiver, set local */ options.c_cflag &= ~CSIZE; /* Clear data length */ options.c_cflag |= CS8; /* Character size = 8 bits */ options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_cflag &= ~CSTOPB; /* Remove 2nd stop bit */ options.c_iflag |= (IXON | IXOFF | IXANY); /* Enable SW flow ctr */ options.c_cflag &= ~CRTSCTS; /* Disable HW flow ctr */ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* RAW input */ options.c_oflag &= ~OPOST; /* RAW output */ tcsetattr(fd, TCSANOW, &options); /* set attributes immediately */ return 1; } } /* InitPort */ int WritePort(char Command[]) { char *BufPtr; int i; BufPtr = Command; for (i=0; i= 'a' && *string <= 'z') ? *string -= OFFSET : *string; Found = 1; string++; } return Found; } /* to_upper */ int strnum(char *string) { int Numeric = 1; int Comma = 0; int ind = 0; while (*string) { if (*string == '.') Comma++; Numeric = ((*string >= '0' && *string <= '9') || *string == '.') ? Numeric : 0; string++; ind++; } if (ind == 0 || Comma > 1) Numeric = 0; return Numeric; } /* strnum */ int ReadVal(char *Address) { char Vquery[Wsize] = ""; tcflush(fd, TCIFLUSH); WritePort(Address); usleep(30000); WritePort(":VOL?;"); usleep(30000); ReadPort(Vquery); char *Vstring = Vquery; char *Volt = Vstring+2; char Vdeal[6] = ""; strncpy(Vdeal, Volt, 5); printf("Actual voltage %s [V]\n", Vdeal); char Aquery[Wsize] = ""; WritePort(":CUR?;"); usleep(30000); ReadPort(Aquery); char *Astring = Aquery; char *Amps = Astring+2; char Adeal[6] = ""; strncpy(Adeal, Amps, 5); printf("Actual current %s [A]\n", Adeal); return (1); } /* ReadVal */ int ReadReg(char *Address) { const char delimiters[] = "PAVLOS"; char *token, Query[Wsize] = ""; char **words = (char **)malloc(sizeof(void *)*sizeof(Query)); if (words == NULL) {perror("Unable to allocate memory\n"); exit(1);} tcflush(fd, TCIFLUSH); WritePort(Address); usleep(30000); WritePort(":STT?;"); usleep(30000); ReadPort(Query); char *string = Query; int windex = 0; while ((token = strsep(&string, delimiters)) != NULL) { if (*token != 0x00) { for (int i=0; i 80.00) {printf("Current value out of range\n"); return (0);} snprintf(Result, sizeof(Result), ":CUR%05.2f;", Current); tcflush(fd, TCIFLUSH); WritePort(Address); usleep(30000); WritePort(Result); usleep(30000); WritePort(":CUR!;"); usleep(30000); ReadPort(Query); char *string = Query; char *amps = string+2; char deal[6] = ""; strncpy(deal, amps, 5); printf("Set current %s [A]\n", deal); return (1); } /* SetAmps */ int SetVolt(char *Address, char *Value) { char Result[12] = ""; char Query[Wsize] = ""; double Voltage = atof(Value); if (!strnum(Value)) {printf("Voltage value is not numeric\n"); return (0);} if (Voltage < 0.000 || Voltage > 10.000) {printf("Voltage value out of range\n"); return (0);} snprintf(Result, sizeof(Result), ":VOL%06.3f;", Voltage); tcflush(fd, TCIFLUSH); WritePort(Address); usleep(30000); printf("command %s\n", Result); WritePort(Result); usleep(30000); WritePort(":VOL!;"); usleep(30000); ReadPort(Query); char *string = Query; char *volt = string+2; char deal[6] = ""; strncpy(deal, volt, 5); printf("Set voltage %s [V]\n", deal); return (1); } /* SetVolt */ int PowerUP(char *Address, char *Value) { char Result[8] = ""; int Action = 0; to_upper(Value); if (!strncmp(Value,"ON", 3) || !strncmp(Value,"1",2)) {strncpy(Result, ":OUT1;", 7); Action = 1;} if (!strncmp(Value,"OFF",4) || !strncmp(Value,"0",2)) {strncpy(Result, ":OUT0;", 7); Action = 1;} if (Action) { WritePort(Address); usleep(30000); WritePort(Result); usleep(30000); } else {printf("Non a binary choice for output\n"); return (0);} return (1); } /* PowerUP */ int RunFile(char *Value) { /* Open file for read */ FILE *fp = fopen(Value, "r"); if (fp == NULL) {printf("no ini file found\n"); return (0);} fseek (fp, 0, SEEK_END); long lSize = ftell(fp); rewind(fp); /* allocate buffer for the entire file */ char *string = (char *) malloc(sizeof(char) *lSize); char **words = (char **)malloc(sizeof(void *)*lSize); if (string == NULL || words == NULL) {perror("Unable to allocate memory\n"); exit(1);} /* copy the entire file into buffer */ fread(string, 1, lSize, fp); fclose(fp); /* search for command delimiters */ int windex = 0; while ((( *(words + windex) = strsep(&string, ":")) != NULL)) { char *token = strsep((words + windex), ";"); char Command[12] = ""; /* action skipping any preambles, header etc before the first command */ if (windex > 0) { snprintf(Command, sizeof(Command), ":%s;", token); printf("command %s\n", Command); WritePort(Command); usleep(30000); } /* if windex */ windex++; } /* while */ /* free up memory */ free (string); free (words); return (1); } /* RunFile */ int RunCMD(char *Address, char *Value) { if (strlen(Value) > 12) {printf("Command not recognised\n"); return (0);} char *Rlist[] = { ":MDL?;", ":REV?;", ":RMT?;", ":OUT?;", ":VOL!;", ":CUR!;", ":VOL?;", ":CUR?;", ":FLD?;", ":OVP?;", ":UVP?;", ":AST?;", ":STA?;", ":ALM?;", ":STP?;", ":STT?;", ":SRV?;", ":SRT?;", ":SRF?;", }; char *Wlist[] = { ":ADRx;", ":RMTx;", ":CURxx.xx;", ":VOLxx.xxx;", ":OUTx;", ":FLDx;", ":OVPxx.x;", ":UVPx.xx;", ":ASTx;", ":SRVx;", ":SRTx;", ":SRFx;", }; #define n_Rlist (sizeof (Rlist) / sizeof (const char *)) #define n_Wlist (sizeof (Wlist) / sizeof (const char *)) int Rfound = 0, Wfound = 0, token = 0; /* Read command found */ for (int i=0; i <,> <:> <;>)\n", stdout); fputs("
LOAD execute macro \n", stdout); fputs("
AMPS alter current \n", stdout); fputs("
VOLT alter voltage \n", stdout); fputs("
GATE / energise output\n", stdout); fputs("
VERB command 'as is'\n", stdout); fputs("
READ read actual V/A\n", stdout); fputs("
STAT module status \n", stdout); fputs(" HELP command menu \n", stdout); fputs(" QUIT quit program \n", stdout); fputs("\n", stdout); return (1); } /* Help */ int main(void) { const char delimiters[] = " ,;\t"; int i, j; if (!InitPort()) return 0; /* Hello world */ fputs("Welcome to ZUP control\n\n", stdout); fputs("List of commands (delimeters <,> <:> <;>)\n", stdout); fputs("
LOAD execute macro \n", stdout); fputs("
AMPS alter current \n", stdout); fputs("
VOLT alter voltage \n", stdout); fputs("
GATE / energise output\n", stdout); fputs("
VERB command 'as is'\n", stdout); fputs("
READ read actual V/A\n", stdout); fputs("
STAT module status \n", stdout); fputs(" HELP command menu \n", stdout); fputs(" QUIT quit program \n", stdout); fputs("\n", stdout); /* eternal loop */ while (1) { /* allocate buffers */ char *string = (char *) malloc(sizeof(char) * Wsize); char **words = (char **)malloc(sizeof(void *) * Wsize); if (string == NULL || words == NULL) {perror("Unable to allocate memory\n"); exit(1);} /* text read input parameters */ fputs("\n", stdout); fputs("Enter Ch# Command Value(opt): ", stdout); fflush(stdout); fgets(string, Wsize, stdin); /* bail on no input */ if (*string == '\n') continue; /* check and save the last character for ";" required by verbatim command */ int Term = 0; if (strncmp(string + strlen(string)-2, ";", 1) == 0) Term = 1; /* parse words in the text */ int windex = 0; while (((*(words+windex) = strsep(&string, delimiters)) != NULL) && windex < 3) windex++; /* get rid of this pesky LF at the end of the last input argument */ char *index = *(words + windex - 1); for (i=0; i<=strlen(index); i++) if (*(index+i) == '\n') *(index+i) = 0x00; // while (*index) if (*index == '\n') *index = 0x00 /* Looking up for QUIT and HELP commands at the start */ char Command[6] = "", Address[100] = "", Value[Wsize] = ""; strncpy(Command, *words, 5); to_upper(Command); /* upper case for latin alphabet */ if (strncmp(Command, "QUIT", 5) == 0) break; /* while(1) */ if (strncmp(Command, "HELP", 5) == 0) {Help(); continue;} if (!strnum(Command)) {printf("ZUP address syntax invalid\n"); continue;} /* Formatting device address */ int Range = (atoi(Command) > 0) && (atoi(Command) <32); /* Address range 1...31 */ sprintf(Command, "%.2d", atoi(Command)); if (Range) snprintf(Address, sizeof(Address), ":ADR%s;", Command); else {printf("ZUP address out of range\n"); continue;} /* Parsing Commands and arguments */ for (i=0; i 1) strncpy(Command, *(words + 1), 5); if (strlen(Command) == 0) {printf("No valid command\n"); continue;} int Robot = 0; to_upper(Command); if (strncmp(Command, "QUIT", 5) == 0) break; /* while(1) */ if (strncmp(Command, "HELP", 5) == 0) Robot = 2; if (strncmp(Command, "READ", 5) == 0) Robot = 3; if (strncmp(Command, "STAT", 5) == 0) Robot = 4; if (strncmp(Command, "LOAD", 5) == 0) Robot = 5; if (strncmp(Command, "AMPS", 5) == 0) Robot = 6; if (strncmp(Command, "VOLT", 5) == 0) Robot = 7; if (strncmp(Command, "GATE", 5) == 0) Robot = 8; if (strncmp(Command, "VERB", 5) == 0) Robot = 9; if (windex > 2) strncpy(Value, *(words + 2), Wsize); if (strlen(Value) == 0 && Robot > 4) {printf("No valid argument\n"); continue;} char nValue[1000] = ""; if (Term) snprintf(nValue, sizeof(nValue), "%s;", Value); switch (Robot) { // case 1: return(0); /* QUIT, no arguments required */ case 2: {Help(); break;} /* Print commands */ case 3: {ReadVal(Address); break;} /* read terminal values, no arguments required */ case 4: {ReadReg(Address); break;} /* read machine status, no arguments required */ case 5: {RunFile(Value); break;} /* Run macro from a file, no address required */ case 6: {SetAmps(Address, Value); break;} /* Set maximum current */ case 7: {SetVolt(Address, Value); break;} /* Set operating voltage */ case 8: {PowerUP(Address, Value); break;} /* Energise terminals */ case 9: {RunCMD(Address, nValue); break;} /* Run verbatim command, no address required */ default: printf("No valid command\n"); } /* Robot */ free(words); free(string); } /* while(1) */ close(fd); return 1; } /* main */