pinewell's farmer blog 農業と電子工作、ソフトウェア、バイク、車

2024年1月4日

対応機種について

Filed under: GNSS,ポチトン — pinewell @ 4:37 PM

「ポチトン」の対応予定機種です。

メーカー型名対応可否対応(予定)日付
AgLeaderInCommand12002023/12/28
InCommand8002024/1/4
TrimbleGFX-12602024/1/5
GFX-10602024/5/1
GFX-7502024/1/5
GFX-3502024/1/5
CFX-750×
TOPCONX35×
X25×
CHCNAVNX5102023/12/28
FJDAT12024/5/1
AT22024/5/1
◯は自動操舵ON/OFFのみ。◎は転回操作についても動作を確認できたもの×は対応予定無

FJD用のポチトンは専用設計。スイッチ2は面性計量に割り当てられています。

動作確認動画

AgLeader InCommand800に対応

Filed under: GNSS,ポチトン — pinewell @ 11:47 AM

「ポチトン」ですが、ご近所さんでお持ちの方がいましたのでInCommand800に対応致しました。

2024年1月3日

お披露目とQ&A

Filed under: GNSS,ポチトン — pinewell @ 11:07 PM

「USB接続自動操舵ON/OFFスイッチ」(通称ポチトン)です。

本日杉山農場さんに紹介いただき、全国・全世界にお披露目となりました。杉山様、有難うございます。

ご注文してくださった方、誠に有難うございます。

いくつか、質問を受けておりますので回答させていただきます。

Q1「GFX-350」には使えないのか?

A1 私自身もいち農家で、すべての自動操舵装置を持っている訳ではありません。今回4機種の対応となったのは近所の方の協力があって実現したものです。

画面のサイズ(解像度)がGFX-750と同じでタッチ位置が同じ場合はGFX-750用の設定で使えるかもしれません。ご協力いただける方が私の近くにいましたなら確認ができます。pinewell@pinewell.jpまでご連絡ください。

槻間農場樣のご協力により、GFX-350でもつかえるようになりました。

Q2 「トプコンx25」には使えないか?

A2 Q1の答えと同じです。ただし、近所でお持ちの方がいるので近日中に確認致します。

Q3 設定を変えることで複数機種で使用できるのか?

A3 はい。DIPスイッチを設定後にUSBに差し直すことで使用機種の変更ができます。

Q4 適格請求書・領収書について

A4 適格請求書発行事業者となっておりますので発行可能です。領収書については振り込みのため割愛させていただきます。

Q5  送料について

A5  現時点では送料は当方負担とさせていただきます。レターパックもしくはクリックポストでの発送となります。

Q6 今月中に指定口座に入金しても大丈夫か?

A6 はい。ただし、現時点で量産化はしておりません。お早く入金いただいても早くて2月上旬の発送となります。

Q7 注文フォームに不具合があるのではないか?

A7 ご迷惑をお掛けして申し訳ありません。なにぶん弱小サーバーなもので負荷に耐えられないこともあったようです。ご不安があるかたは直接 pinewell@pinewell.jpまでメールを送付ください。

「ポチトン」は現時点でも開発中となっています。対応機種についてはまだ増やす余地がありますので北海道内の方でご協力いただける方がいらっしゃいましたらpinewell@pinewell.jpまでご連絡ください。

2024年1月2日

コンパクト版の基板発注

Filed under: GNSS,ポチトン — pinewell @ 10:12 PM

とりあえず10枚のみ。到着が待ち遠しい。

2023年12月29日

プリント基板が届いた

Filed under: GNSS,ポチトン — pinewell @ 5:26 PM

KiCadで作成し、PCBWAYに発注していたプリント基板が届いた。

初めてのコトでうまく行くものかと案じていたが、確かに設計どおり。

実際にパーツをはんだづけして動かしてみたが問題無し。

RP2040-Zeroの穴が若干小さいのを確認できたので修正を行おう。

と言ってもこの基板はテスト用に作成したもので10枚だけ。

現在はスイッチ用のジャックを1つにしたコンパクト版にしたのでまたKiCadと苦闘します。

2023年12月26日

USB接続自動操舵ON/OFFスイッチ

Filed under: GNSS,ポチトン,農業機械 — pinewell @ 12:28 PM

USBキーボードやマウスなどのHIDデバイスに準拠した変換ICであるCH9329とRP2040を用いて、

自動操舵のON/OFFを外部スイッチでできるようにしてみた。

接続はUSBでOK。スイッチを2つ付けることで自動操舵のON/OFF、転回も手元スイッチで可能。

USBマウスのエミュレータなのでタッチパネルの位置情報が把握できれば幅広い機種に対応が可能と思われる。

AgLeader、CHCNAV、Trimble GFX-750では動作確認済み。

近々販売のためのクラウドファンディングを画策中。時間がかかりそうなので中止。

申し込みページを作成しました。
CHCNAVでの動作確認
AgLeaderでの動作確認

2023年2月28日

RasberryPi Picoでの水温計作成 その6 完成

Filed under: その他 — pinewell @ 11:25 PM

本日、2月の最終日だが10度を超える気温となったので家の前の舗装をだしてGL400を引っ張りだした。

カフェレーサー化もほぼ終了しあとは若干の塗装と磨きを残す。

3Dプリンタで作った側に装着して搭載。

w=が水温で48.8度。o=が外気温で8.9度。時間は14:21:19。

懸念していたOneWireでの温度取得もほぼ問題ないようできちんと温度が取得できている。大満足。

ちなみに本来のサーモユニットを抜き取り、アマゾンで購入した「グリース継手 ストレート継手 ステンレス製 アクセサリー スレッド 液体用 M16 x 1.5 mm」

を6mmのドリルで貫通させてDS18B20をJ-Bウエルド クイックウェルド 超強力接着剤 KW-20Zで装着している。

GL400Cafe

2023年2月16日

RasberryPi Picoでの水温計作成 その5

Filed under: その他 — pinewell @ 11:24 PM

前回アップしたソースではGC9A01に表示させるフォントが気に入らなかった。

さらにbitmapの表示がどのようにしたらよいものかわからなかったので新たに探してみた。

https://github.com/russhughes/gc9a01_mpy

結果上記のサイトに行きつき、jpgファイル、.pyファイルへ変換してのbitmapファイルの表示方法が分かった。

とりあえず動作はする。実際に車載したときにどうなるか。

from machine import Pin,SPI,I2C,PWM
import gc9a01 # 内包されているfirmwareを使うこと。
import onewire, ds18x20
import time,utime,math

from ds1307 import DS1307 #libフォルダ

from fonts import chango_16 as fontA
from fonts import chango_32 as fontB

import hondaWing #bitmapのpythonスクリプト

def main():
    #iniファイルの保存
    def SaveIniFile(filename, dictionary):
        with open(filename, "w") as f:
            for key in dictionary:
                f.write("{},{}\n".format(key, dictionary[key]))
    #iniファイルの読み取り
    def LoadIniFile(filename):
        dictionary = {}
        with open(filename, "r") as f:
            for s in f:
                lst = s.strip().split(",")
                dictionary[lst[0]] = lst[1]
        return dictionary
    #使い方
    #data = {}
    #data["Name"] = "Hippy"
    #data["Year"] = "2021"
    #SaveIniFile("/MyData.ini", data)
    #data = LoadIniFile("/MyData.ini")
    #print(data)
      
  
       
    #arduinoのMAP関数
    def convert(x, in_min, in_max, out_min, out_max):
        return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min

    #円を書いて塗りつぶす
    def circle(x,y,r,c):
       tft.hline(x-r,y,r*2,c)
       for i in range(1,r):
           a = int(math.sqrt(r*r-i*i))#平方根だって
           tft.hline(x-a,y+i,a*2,c)
           tft.hline(x-a,y-i,a*2,c)
    #円を書く
    def ring(x,y,r,c):
        tft.pixel(x-r,y,c)
        tft.pixel(x+r,y,c)
        tft.pixel(x,y-r,c)
        tft.pixel(x,y+r,c)
        #lcd.display()
        #utime.sleep(0.1)
        for i in range(1,r):
            a = int(math.sqrt(r*r-i*i)) # Pythagoras
            tft.pixel(x-a,y-i,c)
            tft.pixel(x+a,y-i,c)
            tft.pixel(x-a,y+i,c)
            tft.pixel(x+a,y+i,c)
            tft.pixel(x-i,y-a,c)
            tft.pixel(x+i,y-a,c)
            tft.pixel(x-i,y+a,c)
            tft.pixel(x+i,y+a,c)
            
    data = LoadIniFile("ini.ini")
    dspMode=data["dspMode"]
    face=("FaceA.jpg","FaceD.jpg")
   
    modePin=21  #時刻合わせモードに移行スイッチ
    upPin=20    #日付・時計あわせのアップスイッチ

    cds = machine.ADC(0) #明るさセンサー GP26がADC0
    # 16bitの数値一単位での電圧値を設定します
    unit = 0.00005035477
    
    kurai = 20000  #暗いとき
    akarui = 65535 #明るいとき
    
    dspMode = 0  #0:アナログ 1:デジタル
    mode    = 0  #0:通常 1:時計合わせ 
    sec     = 0  #時計合わせの時のセクション 0:Year 1:month 2 day 3 hour 4 minute 
    uYear   = 0  #時計あわせようの値
    uMonth  = 0
    uDate   = 0
    uHour   = 0
    uMinute = 0

    epSec = 0

    swMode = machine.Pin(modePin,machine.Pin.IN,machine.Pin.PULL_DOWN) #スイッチの定義
    swUp   = machine.Pin(upPin,machine.Pin.IN,machine.Pin.PULL_DOWN)   #スイッチの定義

    pushStart =0 #押し始めた時間
    flgPush = False #押しているか
    pushInt = 0 #押されていた時間

    DSPIN = 19 #温度計のPin。onewire
    dsCnt = 0  #温度計の数
    
    ds_pin = machine.Pin(DSPIN)
    ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin)) #温度計を定義
    
    pw33 = machine.Pin(18,machine.Pin.OUT)   #RTCの3.3Vを得るため
    pw33.value(1)
    
    tokei=True #RTCが取得できたかフラグ


    try:   #RTCから現在時刻の取得
      i2c_rtc = I2C(0,scl = Pin(17),sda = Pin(16),freq = 100000) #RTCの定義
      result = I2C.scan(i2c_rtc)

      rtc = DS1307(i2c_rtc)
      (year,month,date,day,hour,minute,second,p1)=rtc.datetime()

      #RTCから取得した時間を元に 2021/1/1 00:00:00(RP2040のリセット時間)との差分を作成
      epSec = utime.mktime((year,month,date,hour,minute,second,0,0)) #1970/1/1 00:00:00からの経過秒
      epSec = epSec-1609459200
      
      if year==2000:#RTCからの初取得は2000年となるのでその場合に 2023/2/2 12:00:00にRTCを設定 
          year = 2023
          month = 2 
          date = 2 
          day = 4 
          hour = 12
          minute = 0
          second = 0
        
          now = (year,month,date,day,hour,minute,second,0)
          rtc.datetime(now)
    except:
        print("not Tokei")  #RTCから取得できなかったら tokei非表示
        tokei=False
        
    o_ds = bytearray(b'(\x07\x83t/!\x01(') #温度計の個体を特定 外気温
    w_ds = bytearray(b'(?\x9b8/!\x01\xd4') #                水温
    
    try:
        roms = ds_sensor.scan()  #センサーを取得
        dsCnt=len(roms)          #センサー数を得る
        for rom in roms:
            print('Found DS devices: ', rom)
    except:
        dsCnt = 0
    
    #液晶ディスプレイの定義
    spi = SPI(1, baudrate=60000000, sck=Pin(10), mosi=Pin(11))
        
    tft = gc9a01.GC9A01(#バックライトはPWMで調整するので指定しない。
        spi,
        240,
        240,
        reset=Pin(12, Pin.OUT),
        cs=Pin(9, Pin.OUT),
        dc=Pin(8, Pin.OUT),
        rotation=0)

    #バックライトはPWMで調整
    pwm = PWM(Pin(25))
    pwm.freq(1000)
    pwm.duty_u16(akarui)
    tft.init()
    
    tft.jpg(face[dspMode], 0, 0, gc9a01.SLOW)
    
    oldx =120
    oldy = 120
    
    
    while True:
        for i in range(100): #バックライトの明るさ調整
            # ADCの値を読み込みます(16bitの生の数値)
            voltRaw = cds.read_u16()
            #print("voltRaw:" + str(voltRaw))
            volt = voltRaw * unit
            #print( "volt:" + "{:.3f}".format(volt))
        if volt > 2:
            pwm.duty_u16(kurai)
        else:
            pwm.duty_u16(akarui)
 
        #モードスイッチが押されているか?
        if swMode.value() == 1:
            if flgPush : #長押中
                pushInt = utime.time()-pushStart
            else:
                flgPush = True #長押し計測スタート
                pushStart = utime.time()
                pushInt = 0
        else:
            if flgPush :# すでに押されていて離した
                flgPush=False
                pushInt=utime.time()-pushStart #押していた時間を取得
                if pushInt > 2: #長押しされた
                    #print("long") 
                    if mode ==0: #時計合わせモードに移行
                        tft.fill(gc9a01.WHITE)
                        (uYear,uMonth,uDate,day,uHour,uMinute,second,p1)=rtc.datetime() #
                        mode=1
                        sec=0
                    else:   #時計合わせモードで長押し
                        if sec == 4:#分まで設定してたら時計合わせ終了
                            now = (uYear,uMonth,uDate,0,uHour,uMinute,0,0)
                            rtc.datetime(now)
                            sec=0
                            mode=0
                            tft.fill(gc9a01.WHITE)
                            tft.jpg(face[dspMode], 0, 0, gc9a01.SLOW)
                            oldx=120
                            oldy=120
                        else:#次のセクションへ移行
                            sec=sec+1
                else:
                    print("short") #短押しは表示モード切り替え
        #調整用UPボタンの処理
        if swUp.value() == 1:
            #print("up")
            if tokei : #時計表示ができる。 
                if mode == 1: #時刻調整モード
                    utime.sleep_ms(200)        
                    if sec ==0:
                        uYear=uYear+1
                        if uYear>2100:
                            uYear=2023
                    elif sec ==1:
                        uMonth=uMonth+1
                        if uMonth>12:
                            uMonth=1
                    elif sec ==2:
                        uDate=uDate+1
                        if uDate>31:
                            uDate=1
                    elif sec ==3:
                        uHour=uHour+1
                        if uHour>23:
                            uHour=0
                    elif sec ==4:
                        uMinute=uMinute+1
                        if uMinute>59:
                            uMinute=0
                else :
                    #時刻設定モードじゃ無い場合は表示モード切り替え
                    if dspMode==0:
                        dspMode=1
                        tft.jpg(face[dspMode], 0, 0, gc9a01.SLOW)
                        data["dspMode"] = dspMode
                        SaveIniFile("/ini.ini", data)
                    else:
                        dspMode=0
                        data["dspMode"] = dspMode
                        SaveIniFile("/ini.ini", data)
                        tft.jpg(face[dspMode], 0, 0, gc9a01.SLOW)
                        oldx=120
                        oldy=120
                        
                #print(str(uYear)+"/"+str(uMonth)+"/"+str(uDate) + "  " + str(uHour)+":"+str(uMinute)+":00")

        
        if mode ==0: #通常表示
            #温度の取得
            oTemp = 999.99
            wTemp = 999.99
            oReadErr=""
            wReadErr=""
            if dsCnt > 0 :#温度計の数が0以上だったら
                flgSuc=True
                try:
                    ds_sensor.convert_temp()
                    utime.sleep_ms(750)
                except:
                    flgSuc=False
                if flgSuc:
                    for rom in roms:
                        if rom == o_ds :
                            buf = oTemp
                            try:
                                oTemp = ds_sensor.read_temp(rom)
                                oReadErr="O"
                            except:
                                oReadErr="X"
                                oTemp=buf
                        else :
                            buf = wTemp
                            try:
                                wTemp = ds_sensor.read_temp(rom)
                                wReadErr="O"
                            except:
                                wReadErr="X"
                                wTemp=buf
            
            if dspMode==0:
                wwTemp = 20 #最小温度            
                if wTemp <=120 or wTemp > 20: #読み取れている?
                    wwTemp = wTemp
        
                kakudo = convert(wwTemp,20,120,40,320) #角度を取得
                rad = 3.14*kakudo/180 #ラジアン値に変換
                r=90  #針の長さ
                x = int(r*(math.cos(rad))) + 120 #座標を求める
                y = int(r*(math.sin(rad))) + 120 

                c=gc9a01.BLACK
                if wTemp >80:
                    c=gc9a01.RED
                elif wTemp<40:
                    c=gc9a01.BLUE
            
                tft.write(fontA, "w={:.1f}  ".format(wTemp),150,105,c,gc9a01.WHITE)
                tft.write(fontA, "o={:.1f}  ".format(oTemp),155,120,gc9a01.BLACK,gc9a01.WHITE)
        
                if (x != oldx) or (y !=oldy) :
                  tft.line(122, 120 ,oldx ,oldy, gc9a01.WHITE)
                  tft.line(121, 121 ,oldx ,oldy, gc9a01.WHITE)
                  tft.line(120, 120, oldx, oldy, gc9a01.WHITE)
                  tft.line(120, 119 ,oldx ,oldy, gc9a01.WHITE)
                  tft.line(120, 121, oldx, oldy, gc9a01.WHITE)
                  tft.line(119, 119 ,oldx ,oldy, gc9a01.WHITE)
                  tft.line(119, 120 ,oldx ,oldy, gc9a01.WHITE)
                  tft.line(118, 120 ,oldx ,oldy, gc9a01.WHITE)
                  tft.line(120, 118 ,oldx ,oldy, gc9a01.WHITE)

                  tft.write(fontA, "20",175, 162,gc9a01.BLACK,gc9a01.WHITE)
                  tft.write(fontA, "40",94, 190,gc9a01.BLACK,gc9a01.WHITE)
                  tft.write(fontA, "60",40, 148,gc9a01.BLACK,gc9a01.WHITE)
                  tft.write(fontA, "80",40, 77,gc9a01.BLACK,gc9a01.WHITE)
                  tft.write(fontA, "100",94, 31,gc9a01.BLACK,gc9a01.WHITE)
                  tft.write(fontA, "120",175, 61,gc9a01.BLACK,gc9a01.WHITE)
                  tft.bitmap(hondaWing,120-int(hondaWing.WIDTH/2),50)
          
                  tft.line(122, 120 ,x ,y, gc9a01.RED)
                  tft.line(121, 121 ,x ,y, gc9a01.RED)
                  tft.line(120, 120, x, y, gc9a01.RED)
                  tft.line(120, 119 ,x ,y, gc9a01.RED)
                  tft.line(120, 121, x, y, gc9a01.RED)
                  tft.line(119, 119 ,x ,y, gc9a01.RED)
                  tft.line(119, 120 ,x ,y, gc9a01.RED)
                  tft.line(118, 120 ,x ,y, gc9a01.RED)
                  tft.line(120, 118 ,x ,y, gc9a01.RED)
        
                  oldx = x
                  oldy = y

                circle(120,120,10,gc9a01.BLACK)
            else :
                # 温度の表示 右寄せ
                tft.write(fontA, "WaterTemp",40,68,gc9a01.BLACK,gc9a01.WHITE)
                w = tft.write_len(fontB,"    {:.2f}".format(wTemp))
                tft.write(fontB, "    {:.2f}".format(wTemp),210-w,86,gc9a01.BLACK,gc9a01.WHITE)
                tft.write(fontA,wReadErr,40,90,gc9a01.BLACK,gc9a01.WHITE)
                tft.write(fontA, "OutTemp",40,128,gc9a01.BLACK,gc9a01.WHITE)
                w = tft.write_len(fontB,"    {:.2f}".format(oTemp))
                tft.write(fontB, "    {:.2f}".format(oTemp),210-w,146,gc9a01.BLACK,gc9a01.WHITE)
                tft.write(fontA,oReadErr,40,150,gc9a01.BLACK,gc9a01.WHITE)

            if tokei :
                it = utime.mktime(utime.localtime()) #ローカルでは 2021/1/1 00:00:00として起動した1970/1/1 00:00:00からの経過秒
                it = it+epSec                        #RTC差分の値とあわせて
                time =   utime.localtime(it)         #本当の現在時刻を生成
                year=time[0]
                month=time[1]
                date=time[2]
                hour=time[3]
                minute=time[4]
                second=time[5]
                if dspMode==1:
                    dateStr = "{0:04d}/ {1:02d}/ {2:02d}  ".format(year,month,date)
                    tft.write(fontA, dateStr,56, 195,gc9a01.BLACK,gc9a01.WHITE)
                    tft.write(fontA, "                ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
                timeStr = "{0:02d}:{1:02d}:{2:02d}  ".format(hour,minute,second)
                tft.write(fontA, timeStr,80, 213,gc9a01.BLACK,gc9a01.WHITE)
                
                
        else: #時計合わせ
            
            dateStr = "{0:04d}/ {1:02d}/ {2:02d}  ".format(uYear,uMonth,uDate)
            tft.write(fontA, dateStr,60, 195,gc9a01.BLACK,gc9a01.WHITE)
            timeStr = "{0:02d}:{1:02d}:00      ".format(uHour,uMinute)
            tft.write(fontA, timeStr,82, 213,gc9a01.BLACK,gc9a01.WHITE)
            if sec ==0:
                tft.write(fontA,"year       ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
            elif sec ==1:
                tft.write(fontA,"month      ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
            elif sec ==2:
                tft.write(fontA,"date       ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
            elif sec ==3:
                tft.write(fontA,"hour       ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
            elif sec ==4:
                tft.write(fontA,"minute ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
        utime.sleep_ms(10)        
main()

2023年2月15日

RasberryPi Picoでの水温計作成 その4

Filed under: その他 — pinewell @ 11:38 PM

実際にはPicoでは無いのだが。

画面

さてなんやかんやあって上記画像通り、アナログでの表示に成功。

sinとかcosとかラジアンとか高校のころ以来。

w=で水温 o=外気温となる。

水温は40℃以下は青色表示、80℃以上は赤表示とする。

ただ問題ががが。実際にエンジンをかけるとノイズなのかまともに動かない。

とりあえずRTCからの時間取得で失敗していたのでRTCから取得はエンジン始動前の1回にしてみた。

その後寒くてエンジン始動も倉庫内の作業も困難で試してない。

2023年2月7日

RasberryPi Picoでの水温計作成 その3

Filed under: その他 — pinewell @ 10:44 PM

Fritzingを改めて使ってみる。

パーツを作るのが面倒・・・。

必要な情報を貼っていく。

RP2040-LCD-1.28

2つあるヘッダのうち、H2のみを使う。

PICO

本来のPicoとはすこーし違うよう。

PiRTC

Pi用のRTC。DS1307は5V駆動なので3.3Vへのロジックレベル変換が内蔵されている。が、3.3Vも繋ぐ必要があるのは誤算だった。

ブレッドボードで再現

これを収めるケースを作らねば。

« Newer PostsOlder Posts »

Powered by WordPress