DNA synthesizer

I have been working on a DNA synthesizer using several solenoid valves and an Arduino Uno. The synthesizer works by pumping different reagents through each solenoid valves according to a sequence of characters (being a compilation of nucleotide letters A, G, T, C, and/or U) given by a text file on a micro SD card. Here is the circuit I have currently:


Here is the current code I have been working with for my Arduino Uno:

/* MIT Open-Source LICENSE:
*
* Copyright 2018 Charles Grassin
* 
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the 
* "Software"), to deal in the Software without restriction, including 
* without limitation the rights to use, copy, modify, merge, publish, 
* distribute, sublicense, and/or sell copies of the Software, and to 
* permit persons to whom the Software is furnished to do so, subject 
* to the following conditions:
* 
* The above copyright notice and this permission notice shall be 
* included in all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

// PINS

#include <Arduino.h>
#include <stdint.h>
#include <SD.h>
#include <SPI.h>
#include <AFMotor.h>
#define MAX_LINE_LEN 80
#include <LiquidCrystal.h>
#define SERIAL_BUFFER_LENGTH 1

int solenoidPin1 = 2;
int solenoidPin2 = 3;
int solenoidPin3 = 4;
int solenoidPin4 = 5;
int solenoidPin5 = 6;
int solenoidPin6 = 7;
int solenoidPin7 = 8;
int solenoidPin8 = 9;
char serialBuffer[SERIAL_BUFFER_LENGTH];
uint8_t currentIndex=0;


void setup() {

const int cs = 10;
  if (!SD.begin(cs)) 
 {
    Serial.println("Card failed to initialize, or not present");
  
    return;
  }
  Serial.println("card initialized.");
  
  // open the file named ourfile.txt
  
  File myfile = SD.open("oligo.txt");

  // if the file is available, read the file
  if (myfile) 
  {
    while (myfile.available())
    {
      Serial.write(myfile.read());
    }
    myfile.close();
  }  
  // if the file cannot be opened give error report
  else {
    Serial.println("error opening the text file");
  } 
  Serial.print("Initializing card...");
  
  

     pinMode(solenoidPin1, OUTPUT);
 pinMode(solenoidPin2, OUTPUT);
 pinMode(solenoidPin3, OUTPUT);
 pinMode(solenoidPin4, OUTPUT);
 pinMode(solenoidPin5, OUTPUT);
 pinMode(solenoidPin6, OUTPUT);
 pinMode(solenoidPin7, OUTPUT);
 pinMode(solenoidPin8, OUTPUT);
 
}

int incomingByte = 0; // for incoming serial data


void loop() {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();

    // say what you got:
    Serial.print("I received: ");
    Serial.println(incomingByte, DEC);
  }

{
   if (Serial.read() == 'A'||'a'){

digitalWrite(solenoidPin1, HIGH); //Switch Solenoid ON
  delay(1000); //Wait 1 Second
digitalWrite(solenoidPin1, LOW); //Switch Solenoid ON
delay(1000); //Wait 1 Second
digitalWrite(solenoidPin6, HIGH);
delay(1000);
digitalWrite(solenoidPin6, LOW);
digitalWrite(solenoidPin7, HIGH);
delay(1000);
digitalWrite(solenoidPin7, LOW);
   }
    }
    {
       if (Serial.read() == 'G'||'g') { //G||g
     digitalWrite(solenoidPin2, HIGH); //Switch Solenoid ON
  delay(1000); //Wait 1 Second
digitalWrite(solenoidPin2, LOW); //Switch Solenoid ON
delay(1000); //Wait 1 Second
digitalWrite(solenoidPin6, HIGH);
delay(1000);
digitalWrite(solenoidPin6, LOW);
digitalWrite(solenoidPin7, HIGH);
delay(1000);
digitalWrite(solenoidPin7, LOW);
}
    }
{
if (Serial.read() == 'C'||'c') {
    digitalWrite(solenoidPin3, HIGH); //Switch Solenoid ON
  delay(1000); //Wait 1 Second
digitalWrite(solenoidPin3, LOW); //Switch Solenoid ON
delay(1000); //Wait 1 Second
digitalWrite(solenoidPin6, HIGH);
delay(1000);
digitalWrite(solenoidPin6, LOW);
digitalWrite(solenoidPin7, HIGH);
delay(1000);
digitalWrite(solenoidPin7, LOW);
  }
}
  {
if (Serial.read() == 'T'||'t'){
 digitalWrite(solenoidPin4, HIGH); //Switch Solenoid ON
  delay(1000); //Wait 1 Second
digitalWrite(solenoidPin4, LOW); //Switch Solenoid ON
delay(1000); //Wait 1 Second
digitalWrite(solenoidPin6, HIGH);
delay(1000);
digitalWrite(solenoidPin6, LOW);
digitalWrite(solenoidPin7, HIGH);
delay(1000);
digitalWrite(solenoidPin7, LOW);
  }
  }
{
  if (Serial.read() == 'U'||'u'){
  digitalWrite(solenoidPin5, HIGH); //Switch Solenoid ON
  delay(1000); //Wait 1 Second
digitalWrite(solenoidPin5, LOW); //Switch Solenoid ON
delay(1000); //Wait 1 Second
digitalWrite(solenoidPin6, HIGH);
delay(1000);
digitalWrite(solenoidPin6, LOW);
digitalWrite(solenoidPin7, HIGH);
delay(1000);
digitalWrite(solenoidPin7, LOW);
}
}

{
   if (Serial.read() == '\0') {
  digitalWrite(solenoidPin8, HIGH); //Switch Solenoid ON
  delay(1000); //Wait 1 Second
digitalWrite(solenoidPin8, LOW); //Switch Solenoid ON
delay(1000); //Wait 1 Second
}
}
}


I can't seem to figure out what is going wrong with the design, but I have a feeling its my "if else" statement code for each solenoid valve. They are supposed to activate when the given letter is read off of the SD card text file, for example solenoidPin1 corresponds to letter A, while solenoidPin6 and solenoidPin7 are reagents that are supposed turn on after each nucleotide solenoid is activated. I am not sure if the current statements are fulfilling this purpose, and would appreciate any feedback.

This is very interesting. Can you show a normal scheme? Fritzing is more for beginners.
Output from 7805 should go to +5V, not to Vin.

Unfortunately I am sort of a beginner with Arduino, but I am happy to supply anything I can. I tried the 5V wiring instead, but have noticed no improvement.

I have also tried testing this code:

int solenoidPin = 2;

void setup() {
  // put your setup code here, to run once:
pinMode(solenoidPin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
digitalWrite(solenoidPin, HIGH);
delay(1000);
digitalWrite(solenoidPin, LOW);
delay(1000);
}

to see if it was just my code problem, however that doesn't seem to be working either. I have replaced the Arduino to make sure it wasn't fried or something but nothing has changed. Any suggestions?

Do you think that a circuit like this would be better?:

It is similar however it incorporates VIN as well.

Can't say if it's better because the first diagram is so hard to read. But at first glance, it seems acceptable, except that the transistor (what I assume is the emitter) is connected to 5V, in the common emitter configuration it should go to ground.

It was not that obvious, which it would be if this were a real schematic. So it would behoove you to use those instead.

Ok gotcha! Thanks for the input. Im going to try this and see how it goes. If you or anyone else has any input on my code that would be great.
In the meantime, here is the schematic for the example circuit I gave above.

Hello abuet
Below you will find a simple keyboard analyzer for your project.

/* BLOCK COMMENT
  https://forum.arduino.cc/t/dna-synthesizer/963214
*/
#define ProjectName "DNA synthesizer - keyboard analyzer"
unsigned long currentTime;

// A, G, T, C, and/or U
void checkKeyboard() {
  if (Serial.available()) {
    switch (Serial.read() | 0x20) { // make lower case
      case 'a': Serial.println("a"); break;
      case 'g': Serial.println("g"); break;
      case 't': Serial.println("t"); break;
      case 'c': Serial.println("c"); break;
      case 'u': Serial.println("u"); break;
    }
  }
}
// -------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  Serial.println(F("."));
  Serial.print(F("File   : ")), Serial.println(__FILE__);
  Serial.print(F("Date   : ")), Serial.println(__DATE__);
  Serial.print(F("Project: ")), Serial.println(ProjectName);
  pinMode (LED_BUILTIN, OUTPUT);  // used as heartbeat indicator
}
void loop () {
  currentTime = millis();
  digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
  checkKeyboard();
}

Have a nice day and enjoy coding in C++.

Both scheme are incorrect wired.
On first - GND is nowhere connected.
On second Picture - Gate connected to +5V.

Solenoid must have 5V working Voltage.
mosfet must be for 15V Vds and 5V Vgs.
VCC 8-12V

Note that R1 should not be 10R but at least 120R to protect against excess current when the FET is turned on.

This is exactly what I was looking for thank you so much! I will let you know how it works out!

Hi,

Vgs must be much lower than 5V.
Vgs is the gate to source voltage needed to START the MOSFET conducting, not at its lowest Drain - Source resistance.
The MOSFET needs to be "Logic Level MOSFET".

Tom... :grinning: :+1: :coffee: :australia:

Continuing the discussion from DNA synthesizer:

Below you will find a simple keyboard analyzer for your project.

I have been using this code along with the circuit given by kolaha

Solenoid must have 5V working Voltage.
mosfet must be for 15V Vds and 5V Vgs.
VCC 8-12V

and I have not seen any progress. I am wondering if the code given is not going to work with SD cards, or If I had just used it incorrectly in my code. I am still using the arduino library example for SD card reading in my void setup () and have made changes to the referenced keyboard reading code for each letter like so:

case 'a': Serial.println("a"); break;
      {
       digitalWrite(solenoidPin1, HIGH); //Switch Solenoid ON
  delay(1000); //Wait 1 Second
digitalWrite(solenoidPin1, LOW); //Switch Solenoid ON
delay(1000); //Wait 1 Second
digitalWrite(solenoidPin6, HIGH);
delay(1000);
digitalWrite(solenoidPin6, LOW);
digitalWrite(solenoidPin7, HIGH);
delay(1000);
digitalWrite(solenoidPin7, LOW);
    }

My current circuit looks like the referenced one given by kolaha, only with all 8 solenoid valves in a repeat of the sequence from pin 2-9, and the voltage regulators placed after every 2 N-Channel transistor.
I can post a full circuit if that is helpful, as well as images of my current arduino and breadboards if needed. If anyone has any feedback it would be greatly appreciated, I'm sort of at a loss here.

Thank you! I am currently using these from amazon:

These are totally unsuitable for your circuit. Driving then with a 5V signal you will only get 75mA of current to pass. Which is not enough.

You should be searching for a "logic level power FET".

Yes that should have been in your first post, but better late than never. No need to post all of it, just one solenoid and the power arrangements, an pin connections on the Arduino.

Thank you so much, I am new to circuitry so this was extremely helpful! I have now been looking at these from amazon:
https://www.amazon.com/Cylewet-RFP30N06LE-0-047Ohm-N-Channel-Arduino/dp/B06W9F1QGF/ref=sr_1_1?crid=29L0RQ92DDNSX&keywords=logic+level+power+FET&qid=1646005229&s=industrial&sprefix=logic+level+power+fet%2Cindustrial%2C116&sr=1-1

I will be getting that circuit up ASAP. Thank you for all of your help!

The code has some problems.

First, you state you want to read from a file on the SD card, but everything in loop is reading from the Serial input, not the SD card.

Second, you do not have a Serial.begin() anywhere in the code, so the Serial port is never properly initialized.

Third, and this is major, you check for Serial.available, and if there is a character available, you read that character and print it to Serial. This character is then never used again. Each of the subsequent if statements read an additional character from the Serial input, without first checking to see if there are any characters available.

void loop() {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();

    // say what you got:
    Serial.print(F("I received: "));
    Serial.println(incomingByte, DEC);
  }

  {
    if (Serial.read() == 'A' || 'a') {

      digitalWrite(solenoidPin1, HIGH); //Switch Solenoid ON
      delay(1000); //Wait 1 Second
      digitalWrite(solenoidPin1, LOW); //Switch Solenoid ON
      delay(1000); //Wait 1 Second
      digitalWrite(solenoidPin6, HIGH);
      delay(1000);
      digitalWrite(solenoidPin6, LOW);
      digitalWrite(solenoidPin7, HIGH);
      delay(1000);
      digitalWrite(solenoidPin7, LOW);
    }
  }

There are a lot of extraneous curly brackets, as well as an unusual mix of coding style pertaining to how to position the curly brackets after an if or while statement.

Yes they are much better and while there are better FETs with a lower turn on resistance, these should do fine for what you need. However did you spot that these were out of stock so I don't know what price they are. Generally parts from Amazon are not very well priced, they tend to be a bit on the expensive side.

Ok I think I understand. Would you suggest I do something like this:

void loop() {

  Serial.begin(9600);
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();

    // say what you got:
    Serial.print("I received: ");
    Serial.println(incomingByte, DEC);
  }

{
  if (Serial.available() > 0){
   if (Serial.read() == 'A'||'a'){

digitalWrite(solenoidPin1, HIGH); //Switch Solenoid ON
  delay(1000); //Wait 1 Second
digitalWrite(solenoidPin1, LOW); //Switch Solenoid ON
delay(1000); //Wait 1 Second
digitalWrite(solenoidPin6, HIGH);
delay(1000);
digitalWrite(solenoidPin6, LOW);
digitalWrite(solenoidPin7, HIGH);
delay(1000);
digitalWrite(solenoidPin7, LOW);
   }
    }
}

There was one thing that I wasn't sure about.

I have been trusting the Arduino library example for SD card reading. I am a little lost on how to specify the opening and reading of an SD card text file, if File myfile = SD.open("oligo.txt"); cant do the job. Do you have any suggestions on how this can be done and be used to reference individual characters in order?
Thank you

Thank you so much! I ordered them since they aren't out of stock in my area, while they are more expensive on Amazon, around $8, it's convenient.