用Arduino Uno制作功能计算机


8

那里有Arduino发烧友吗?

嘿,我一直在考虑这个问题,我思考的越多,我实际就能做到的越多。我的想法基本上是这样的:用Arduino Uno微控制器制造功能计算机。

我对这台计算机的唯一目标是能够编辑和执行BASIC程序。就这样。我只希望将其用于编程,因为那只是我现在唯一感兴趣的事情:)

因此,从我的角度来看,我将需要三个主要的硬件组件:

  1. 某种形式的显示器(VGA屏幕或其他东西)
  2. 注册键盘输入的某种方法,以及
  3. 将数据存储到外部存储器的某种方式。

有人知道这样做吗?我知道在屏幕上显示的方法,但是我不知道用于注册键盘输入或存储外部存储器的优质API /硬件组件。

在这方面,我需要很多帮助。谁能帮我一下,为好的硬件/好的开源库,或者两个,三个或十个提供想法,有用的技巧和建议?

添加:

为感兴趣的人制作Arduino Uno计算机的博客。


这听起来像是我的头发缠结的项目;)我很期待听到您如何处理它。希望您能将自己的进度写博客。
Majenko 2011年

1
我只是想指出一个可能感兴趣的类似项目。就BASIC而言,Parallax Propeller芯片已经取得了很大的发展。至少有两个不同的口译员。另外,它还具有将信号直接输出到监视器电视的功能。
2011年

1
甚至还有具有VGA,电视,PS / 2键盘和鼠标,音频以及更多连接器的演示板。现在我知道您想使用Arduino来做到这一点,但是至少您可以使用那里提供的电路板原理图来获得一些有关它们如何产生信号的基本指示,等等(全部在软件中)。
AndrejaKo 2011年

也想做这样的事情+1!我记得回到小学时,我们从Orao计算机迁移到Pentium III计算机,BASIC失去了它的所有魅力。
2011年

1
使用VGA显示器的另一种方法是拿起LCD护罩并将其用于显示器。您可能需要斜视,但与它的连接将更加轻松!
SingleNegationElimination 2011年

Answers:


11

只需使用PS / 2键盘即可完成键盘-它只是串行的,并且有大量的教程供您参考。

可以简单地在SD卡上存储数据-已经有一个屏蔽罩可以做到这一点。

至于视频-这要困难得多。例如,如果您想让Arduino生成PAL视频信号,那么您的工作就可以完成。是的,有可能,有人创建了一个Arduino“ pong”游戏,但是它的图形非常粗大,只有黑白。

对于VGA,您将需要某种形式的接口来为您完成工作。Sparkfun曾经出售可以与Arduino 配合使用的Picaso 视频卡,但是可惜已经停产了,还没有更换的计划。

TBH最好的选择是使用Wyse终端之类的东西,并完全通过串行与Arduino通信。比弄乱视频信号等简单得多。


3

我在这里看到了Olin的观点-如果您只想使用PC来编辑/运行/学习BASIC。

但是,如果目标是创建一台可以运行BASIC并同时了解硬件和较低级实现的计算机的挑战,则情况有所不同。我全都喜欢这样的事情,这是提高知识的一种很好的方法,并且肯定会从中学到很多。正如史蒂文(Steven)所提到的,可以剥离掉Windows等所有令人困惑的(主要是不相关的)层,从而保留了基本的(无双关语)概念。

无论如何,您可能想看看像PIC32这样功能更强大的东西,因为它应该能够独自处理所有功能(例如基本VGA)。
这是一个Arduino兼容板,UNO32
Maximite是用BASIC解释器的计算机基于一个PIC32,你可能想看看设计和施工的一些想法。


鉴于PC在Z80下运行Microsoft Basic的规格,应该没有真正的问题。
mckenzm

2

有点幸运,因为我现在正在实际使用arduino PC!虽然不是很多,但只有第一个模型。固件也非常简单,并且具有较小的API集。但是,事情正常!不足以编辑BASIC(或除其自身以外的任何语言),但这只是第一个模型。主板很简单,我用了这个。这是我使用的固件:

        #include <LCD4884.h>
#include <SD.h>
#include <SPI.h>
#include <SoftwareSerial.h>

void setup() {   
    lcd.LCD_init();             
    lcd.LCD_clear();
    lcd.LCD_write_string_big(0, 0, "Gilbert", MENU_NORMAL);
    pinMode(10, OUTPUT);
    delay(3000);
}

byte line = 10;
SoftwareSerial FC(8,9);
byte RAM[501];
byte Error = 0;
char tempString[15];

void loop() {
    // <editor-fold defaultstate="collapsed" desc="Initilization">
    FC.begin(4800);
    if (!FC.available()) {
        lcd.LCD_clear();
        lcd.LCD_write_string(0, 0, "FC Failed!", MENU_NORMAL);
        delay(1000);
    }
    int address = 1;
    lcd.LCD_clear();
    lcd.LCD_write_string(0, 0, "SD Init...", MENU_NORMAL);
    if (!SD.begin(10)) {
        lcd.LCD_clear();
        lcd.LCD_write_string(0, 0, "SD Failed!", MENU_NORMAL);
        while (true) {
            ;
        }
    }
    lcd.LCD_clear();
    lcd.LCD_write_string(0, 0, "Loading...", MENU_NORMAL);
    File file;
    file = SD.open("BIOS.mk8", FILE_READ);
    RAM[0] = 53;
    RAM[file.read()] = 8;
    while (file.available()) {
        RAM[address] = file.read();
        address++;
    }
    address++;
    RAM[address] = 55;
    long loops = 0;
    long time1 = 0;
    long time2 = 0;
    address = 0;
    byte instruction = 0;
    int exeaddress;
    byte tempbyte;
    lcd.LCD_clear();
    lcd.LCD_write_string(0, 0, "EMU. Started", MENU_NORMAL);// </editor-fold>
    //emulation loop
    while(true){
        switch(RAM[address]){
            // <editor-fold defaultstate="collapsed" desc="Codes 1-10">
            case 1:
            {//getCycleCount[intvar i]
                tempbyte = (loops) / ((time2 - time1) / 1000);
                convert(address + 1);
                writeInt(exeaddress, tempbyte);
                break;
            }
            case 2:
            {//getTemp[intvar i]
                tempbyte = (((analogRead(A1) / 1024.0) * 5.0) - .5) * 100;
                convert(address + 1);
                writeInt(exeaddress, tempbyte);
                break;
            }
            case 3:
            {//getKey[intvar i]
                //Up 745
                //Down 332
                //Left 0
                //Right 509
                //Center 145
                switch (analogRead(A0)) {
                    case 745:
                    {
                        tempbyte = 1;
                        break;
                    }
                    case 332:
                    {
                        tempbyte = 2;
                        break;
                    }
                    case 0:
                    {
                        tempbyte = 3;
                        break;
                    }
                    case 509:
                    {
                        tempbyte = 4;
                        break;
                    }
                    case 145:
                    {
                        tempbyte = 5;
                        break;
                    }
                }
                convert(address + 1);
                writeInt(exeaddress, tempbyte);
                break;
            }
            case 4:
            {//printLine[variable v]
                if (line > 70) {
                    lcd.LCD_clear();
                    line = 0;
                }
                switch(RAM[address + 1]){
                    case 9:{
                        tempbyte = RAM[address + 1];
                        tempString[0] = char(tempbyte);
                        break;
                    }
                    case 15:{
                        convert(address + 1);
                        break;
                    }
                }
                lcd.LCD_write_string(0, line, tempString, MENU_NORMAL);
                line += 10;
                break;
            }
            case 5:
            {//exe detector
                exeaddress = address;
                break;
            }
            case 7:
            {//lcdClear
                lcd.LCD_clear();
                line = 0;
                break;
            }
            case 10:
            {//declareInteger[string name]
                convert(address + 1);
                tempbyte = 0;
                while (tempbyte != 15) {
                    RAM[address + tempbyte + 1] = tempString[tempbyte];
                }
                break;
            }// </editor-fold>
            case 11:{//getError[intvar i]
                tempbyte = Error;
                Error = 0;
                convert(address + 1);
                writeInt(exeaddress, tempbyte);
                break;
            }
            case 12:{//deadlock
                while(true){;}
                break;
            }
            case 13:{//assignInteger[int value, intvar i]
                tempbyte = RAM[address + 1];
                convert(address + 2);
                writeInt(exeaddress, tempbyte);
                break;
            }
            case 14:{//transferInteger[intvar i1, intvar i2]
                convert(address + 1);
                writeInt(exeaddress, RAM[getIntAddr(exeaddress)]);
                break;
            }
        }
        // <editor-fold defaultstate="collapsed" desc="post loop process">
        address++;
        time2 = millis();
        loops++;
        if (loops < 0) {
            loops = 0;
        }// </editor-fold>
    }
}

void convert(int startAddress){
    byte charadd = 0;
    while(RAM[startAddress] != 6){
        tempString[charadd] = RAM[startAddress];
        charadd++;
        startAddress++;
    }
}

void writeInt(int exeStart, byte value){
    byte count = 0;
    char compare[15];
    while(true){
        if (RAM[exeStart] == 9) {
            exeStart++;
            while (count != 15) {
                compare[count] = RAM[exeStart];
                exeStart++;
                count++;
            }
            if(compare == tempString){
                RAM[exeStart + 2] = value;
                break;
            }else{
                exeStart += 3;
            }
            if(RAM[exeStart] == 8){
                Error = 1;
            }
        }
    }
}

int getIntAddr(int exeStart){
    byte count = 0;
    char compare[15];
    while(true){
        if (RAM[exeStart] == 9) {
            exeStart++;
            while (count != 15) {
                compare[count] = RAM[exeStart];
                exeStart++;
                count++;
            }
            if(compare == tempString){
                return RAM[exeStart + 2];
                break;
            }else{
                exeStart += 3;
            }
            if(RAM[exeStart] == 8){
                Error = 1;
            }
        }
    }
}

方法说明很难解释,但是代码存储为原始字节。我应该尽快安装开发软件...希望对您有所帮助!如果要在任何项目中使用此功能,则必须在SD的根目录上具有BIOS.mk8文件,否则系统将无法工作。


1
的确很幸运,如果他自从首次提出问询以来的三年中一直没有想通
斯科特·塞德曼

@ScottSeidman是的,很好。另外,固件仍在测试中,该版本缺少关键要素。
哈卡2014年

1

戴维·布林(David Brin)受到所有应有的尊重(我碰巧很喜欢他的书;我没有资格判断他作为天体物理学家有多出色),他既不是程序员也不是教育家。

在PC早期,我就在这里并进行编码,并且编写了大量的BASIC代码。从那时起,我一直在专业地编写代码。

当时我们使用BASIC的原因是,您的两个选择是使用BASIC或以汇编形式编写,而汇编既难以理解,又使用起来更加麻烦。如此基础。

从那以后的30多年中,编程指令有了重大改进。我的妻子教一个使用Alice(www.alice.org)的编程入门课程,从概念上讲,它比以前的方法要好得多。

我认为Brin的解决方案非常优雅。您可以在Raspberry PI上构建非常简单的东西。在arduino上,我认为将所需的所有内容填充到2K RAM中将是一个挑战。它必须容纳您最终编写的任何OS / Monitor,命令解释器,执行显示的代码以及基本程序本身的存储。

更不用说您将不得不做大量的困难和自定义编程的事实,以便您可以在简单的环境中编写代码。


0

我不明白 如果只希望使用Basic编程,请在PC上运行基本解释器。我不明白您对Arduino的期望如何。Arduino是一个带有大量精美软件的微控制器,可以隐藏硬件细节。与直接在裸露的微控制器上运行的等效程序相比,这样做的部分代价是性能较低,资源占用更多。现在,您想编写Arduino代码以将其转换为更通用的计算机,所有这些都可以让您依次在该通用计算机上运行Basic解释器吗?这毫无意义。

由于您的唯一目标是能够编辑和执行Basic程序(运行Basic解释器),因此首先要从更通用的计算平台入手,最好甚至是已经具有Basic解释器的平台。您的PC就是这样一个平台。如果您希望这是外部硬件,听起来像是现成的单板计算机将比Arduino更好地满足您的需求。

添加:

现在,您说您不想在PC上运行,并在此链接上找到有关某人想要命令行基础供其孩子学习的链接。诚然,我没有阅读整篇文章(我不喜欢人们用链接回答。您应该能够用几句话独立地陈述您的观点),但是我看不到PC如何运行命令行基本解释器无法解决您的问题。为什么不允许基本解释器在PC上运行,但可以在Arduino上运行呢?记住,您之前说过,您的唯一目标是编辑和运行Basic程序。该声明中没有任何内容说明必须在什么硬件上运行,并且您随后的解释也都没有解释为什么PC无法正常运行。

可能有一些在命令行上运行的基本解释器。旧的QBASIC可能仍在某些DOS兼容模式下工作。即使不这样做,由于您愿意为此付出专用的硬件,因此如何在PC上运行DOS和QBASIC不能满足您的要求?


我的观点是我不想在PC上编程。我想在与例如Texas Instruments TI-84 +类似的环境中进行编程。我的原因是什么?请查看以下链接,“为什么Johnny无法编码” salon.com/technology/feature/2006/09/14/basic/index.html
Lincoln Bergeson 2011年

3
这不是真正的答案。是的,OP的想法可能有点中心,但是如果没有人尝试过任何不同寻常的尝试或将现有的极限推向更高的局面,我们会在哪里?告诉OP这是一个愚蠢的想法,既无益,也无建设性。OP已决定他愿意这样做,并正在寻求我们的帮助。他不是在问这是一个好主意。是的,这很可能是Bad Idea™,但是OP在发现这一点的同时会学到很多东西,这本身比最终结果更有价值。
Majenko 2011年

@Majenko:我写的是OP最初写的合理答案。记住,他说:“ 我对这台计算机的唯一目标是能够编辑和执行BASIC程序 ”。这没有说明在备用硬件上运行。显然,他想要一个简单的命令行基本解释器来教孩子。如何在PC上运行这样的事情不是有效的答案?一台运行QBASIC的PC还是他所要求的东西?
Olin Lathrop

1
@Olin OP同意我的观点...我认为您是在解释错误的问题。
Majenko 2011年

2
@Olin-我能理解屁股。还记得70年代末80年代初的家用计算机吗?您添加了一个内存映射74LS373,可以通过poke语句控制I / O。没有要安装的虚拟COM驱动程序,没有USB连接到任何网桥,没有要加载的复杂开发人员IDE。SBC具有可比性,但通常缺少家用计算机的键盘/视频接口(和盒式磁带存储!)。
stevenvh 2011年


0

我喜欢在Arduino上运行通用应用程序(例如BASIC)的想法,特别是如果您自己手工构建的话。我喜欢使用方便的电池供电的Arduino设备运行我想要的应用程序带来的便利。如果是我,我可能会使用Arduino MEGA,因此我将有足够的引脚用于键盘和SD屏蔽板用于存储。

为了简化编程和连接,跟踪日期和时间(RTC)的方式,我会选择彩色图形LCD或VGA上的TFT屏幕,以及没有互联网或网络(以太网屏蔽)的应用程序是什么?可能需要额外的I2C RAM(24LC256)?还有一些I2C MCP223017,以防万一我需要一些额外的端口。多个Arduino做并行任务怎么样?我敢肯定,那将改善性能。


社区赞赏与数据表的链接。另外,请不要使用太多大写字母,并通过添加空格来确保您的答案可读。

2
实际上,这是一个质量很差的答案。但是,这里有一些情感,如果需要清理和更好地表达,可能是值得的。
克里斯·斯特拉顿
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.