2021年4月28日 星期三

[C#] 連接到MySQL

 1.先載入參考(MySQL.Data)

    專案中的參考(右鍵)=>加入參考=>"組件"中尋找MySQL.Data

2.建立ConnectString

  private static MySqlConnectionStringBuilder MySQL => new MySqlConnectionStringBuilder
  {
     Server = "127.0.0.1",	//MySQL的位置或URL(127.0.0.1為本地)
     Port = 3306,		//MySQL預設Port為3306
     UserID = "Username",	//MySQL的使用者帳號
     Password = "Password",	//MySQL的使用者密碼
     Database = "mydb",		//MySQL的DB名稱
     CharacterSet = "utf8"	//MySQL的字元集
  };
3.讀取MySQL
   讀取DB內的table的所有資料至DataSet,
   相關的資料操作請參考DataSet。

  private static DataSet GetDataFromMySQL()
  {
   DataSet ds;
   using (var conn = new MySqlConnection(MySQL.ConnectionString))
   {
    const string sql = @" SELECT * FROM `tableName`";
    using (var adapter = new MySqlDataAdapter(sql, conn))
    {
     try
     {
      ds = new DataSet();
      adapter.Fill(ds, "tableName");
     }
     catch
     {
      MessageBox.Show(@"Can not connect to database...", @"Message");
      ds = null;
     }
    }
   }
   return ds;
  }

4.更新MySQL

   藉由MySqlDataAdapter會自動生成相關的command,
   如果需要更詳細的調整可自己寫SQL command。
   MySqlDataAdapter會自動判斷並使用相關的command,
   例如:有增加DataRow會使用InsertCommand
            有減少DataRow會使用DeleteCommand
             DataRow無增減,但row內容有改變時,會使用UpdateCommand
  *註: 使用UpdateCommand時要特別注意不可改變DataRow的順序,
          不然MySQL會報內部錯誤。
          避免這問題最好是修改過一個DataRow就Update一次較為保險,
          但遇到資料量大時效率會變差。
public static bool UpdateMySQL(DataTable table)
{
  using (var conn = new MySqlConnection(MySQL.ConnectionString))
  {
   var sql = $@"SELECT * FROM `{table.TableName}`";
   using (var adapter = new MySqlDataAdapter(sql, conn))
   {
    using (var cmd = new MySqlCommandBuilder(adapter))
    {
     adapter.InsertCommand = cmd.GetInsertCommand();//可省略會自動生成,
     adapter.DeleteCommand = cmd.GetDeleteCommand();//也可自己下SQL指令。
     adapter.UpdateCommand = cmd.GetUpdateCommand();
     var updateNum = adapter.Update(table);
     Console.WriteLine($@"更新{updateNum}個檔案");
     return updateNum != 0;
    }
   }
  }
 }

2021年1月20日 星期三

[Arduino]使用PCA9685控制伺服馬達(Servo motor)

 使用PCA9685需先載入Adafruit_PWMServoDriver.h(相關文件)

  以下範例為伺服機先置中(90度,pulse_width=>1500),
  等待一秒後,
  向左轉動60度(30度的位置,pulse_width=>900)。
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

#define FREQUENCY 50
Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver();

void setup() {
  Serial.begin(9600);
  pwm1.begin();
  pwm1.setPWMFreq(FREQUENCY);
  //  pwm1.writeMicroseconds(0, 1500);
  //  pwm1.writeMicroseconds(0, degreeToPulse(90));
  pwm1.setPWM(0, 0, degreeToPWM(90));
  //  pwm1.setPWM(0, 0, pulseToPWM(1500));

  delay(2000);
  //  pwm1.writeMicroseconds(0, 900);
  //  pwm1.writeMicroseconds(0, degreeToPulse(30));
  pwm1.setPWM(0, 0,  degreeToPWM(30));
  //  pwm1.setPWM(0, 0,  pulseToPWM(900));
}

int pulseToPWM(int pulse) {
  return int(float(pulse) / 1000000 * FREQUENCY * 4096);
}

int degreeToPulse(int degree) {
  return map(degree, 0, 180, 600, 2400);
}

int degreeToPWM(int degree) {
  return pulseToPWM(degreeToPulse(degree));
}
 啟動PCA9685
 pwm1.begin();
 設定伺服機接受的頻率,
 手邊的伺服機是50Hz
  pwm1.setPWMFreq(FREQUENCY);
 設定PWM的值,一般Min=>150 Max=> 600
 但每個型號伺服機的值皆不同。

 測試方法:
 如果超過極限值(最大或最小值),
 伺服機就不會激磁(用手可轉動),
 再利用量角器找出相對應的值。 
 pwm1.setPWM(0, 0, pwm_value);
 如果已知pulse_width也可直接輸入,
 設定PCA9685上第幾個伺服機(0~15),
 設定伺服機的pulse_width。
  pwm1.writeMicroseconds(0, 1500);
 小弟我在網路上找資料大多是使用setPWM,
 於是又去找了pulse轉換為PWM值的公式(如下),
 直到去github上的api才看見有writeMicroseconds,
 裡面就寫好了轉換公式。Orz
 1000000為pulseLength
 FREQUENCY為馬達接收的頻率,手邊的為50Hz
 4096為PCA9685發出訊號的解析度(12bits=>4096)
int pulseToPWM(int pulse) {
  return int(float(pulse) / 1000000 * FREQUENCY * 4096);
}
 *註 
 手邊伺服機為模型用的,所以工作電壓為(6V~7.4V),
 實驗過PCA9685的V+(外部供電接腳)可支援到7.4V,
 再上去就需要實驗了,看文件有顆電阻限制在10V以下。

[Arduino]使用PWM控制伺服馬達(Servo motor)

 在Arduino中有寫好一個庫Servo.h可以引用(相關文件)

 以下的範例為馬達先置中(90度),
 一秒後,往左轉60度(轉至30度的位置)。
#include <Servo.h>

int angle = 90;
Servo myServo;

void setup() {
  Serial.begin(9600);
  myServo.attach(4, 600, 2400);
  myServo.write(angle);
  Serial.println(myServo.read());
  delay(1000);
  myServo.write(30);
  Serial.println(myServo.read())
  delay(1000);
}
 設定第幾個pin腳輸出訊號,訊號的pulse_width最大及最小值。
 不同型號Servo的值皆不同,手邊這顆pulse_width值為
     1500=>90度,
     2100=>150度,
     900=>30度,
     可動範圍120度。
 (在Arduino中稱為Microseconds)
 所以推算0度=>600,180度=>2400
 myServo.attach(4, 600, 2400);
 設定Servo的角度(預設0~180)
 myServo.write(angle);
 也可直接寫入pulse_width
    *註 一般認為的pulse,對Arduino來說是pulse_width
 myServo.writeMicroseconds(pulse_width);
 可讀取現在Servo的角度
 myServo.read();
 但是沒有讀取pulse_width(Microseconds)的方法
 所以只能用map作轉換了(相關文件)
 int pulse = map(myServo.read(),0,180,600,2400);